Golang中如何正确设置interface{}的值
Golang中如何正确设置interface{}的值 我有一个Tag结构体,它包含数据类型、值和字节字段。我使用SetValue和SetBytes函数来设置值和对应的字节。当我设置值时,我也会设置字节,反之亦然。
如果有更好或更符合Go语言习惯的方法,请给予建议。
以下是代码:
//data types
const (
Bit uint8 = 1
Uint8 uint8 = 2
Int8 uint8 = 3
//...
)
type Tag struct {
//...
DataType uint8
bytes []byte
value interface{}
}
func (t *Tag) SetBytes(bytesOfValue []byte) error {
//try to set value
var value interface{}
b := bytes.NewReader(bytesOfValue)
var err error
switch t.DataType {
case Bit:
var v bool
err = binary.Read(b, binary.BigEndian, &v)
value = v
case Uint8:
var v uint8
err = binary.Read(b, binary.BigEndian, &v)
value = v
case Int8:
var v int8
err = binary.Read(b, binary.BigEndian, &v)
value = v
//...
}
if err != nil {
fmt.Println(err.Error())
return errors.New("reading bytes failed")
}
t.value = value
//set bytes
t.bytes = bytesOfValue
return nil
}
func (t *Tag) SetValue(value interface{}) error {
//try to set bytes
var v interface{}
var ok bool
switch t.DataType {
case Bit:
v, ok = value.(bool)
case Uint8:
v, ok = value.(uint8)
case Int8:
v, ok = value.(int8)
//...
}
if !ok {
return errors.New("value is not valid")
}
b := new(bytes.Buffer)
err := binary.Write(b, binary.BigEndian, v)
if err != nil {
return errors.New("writing bytes failed")
}
t.bytes = b.Bytes()
//set value
t.value = value
return nil
}
我像这样设置值和对应的字节:
//create tag
t := Tag{
DataType: Int8,
}
//set value
err := t.SetValue(int8(-128))
if err != nil {
fmt.Println(err.Error())
return
}
fmt.Println(t.GetBytes(), t.GetValue())
//set bytes
err = t.SetBytes([]byte{128})
if err != nil {
fmt.Println(err.Error())
return
}
fmt.Println(t.GetBytes(), t.GetValue())
这是Playground链接:https://play.golang.org/p/hHpTIw9Fxx5
此致
更多关于Golang中如何正确设置interface{}的值的实战教程也可以访问 https://www.itying.com/category-94-b0.html
你在开玩笑吗?
如果你对这个主题一无所知,你就不必写!
更多关于Golang中如何正确设置interface{}的值的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
在Go语言中,字段名以大写字母开头才能从其他包访问。
很抱歉打扰您,我之前没有阅读第一篇帖子…
这些问题无关紧要。
你曾经使用过 binary 包的 Read 和 Write 函数吗?
你对这个主题有什么建议,还是仅仅在浪费时间?
请为 t 指定一个数据类型。我没有分享完整的代码。有一个 NewTag 函数用于创建标签。 我也编辑了帖子。
测试你的代码。
//set value
t := Tag{}
fmt.Println(t)
t.SetValue(int8(-128))
fmt.Println(t)
{0 [] <nil>}
{0 [] <nil>}
感谢您抽出时间并给予答复,Petrus。
我的问题是关于重复使用 binary.Read 函数,因为它不接受 interface{} 类型的值。
我继续进行开发和测试。由于这是一个底层的设备通信协议,我无法用现代的方法解释所有的设计标准,并且我不想占用您太多时间,我会考虑您的建议。
此致
请为 t 指定一个数据类型。我没有分享完整的代码。有一个 NewTag 函数用于创建标签。
在设计数据结构时,安排每种类型的零值无需进一步初始化即可使用,这是很有帮助的。这意味着数据结构的用户可以创建一个并立即开始工作。
Yamil_Bracho:
在 Go 语言中,字段名以大写字母开头才能被其他包访问。
你误解了我的问题。
我知道 Go 为什么导出标识符。
标识符可以被导出以允许从另一个包访问它。一个标识符被导出,当且仅当:
- 标识符名称的第一个字符是 Unicode 大写字母(Unicode 类别 “Lu”);并且
- 该标识符在包块中声明,或者它是一个字段名或方法名。
所有其他标识符均未导出。
petrus:
//tag struct type Tag struct { DataType uint8 bytes []byte value interface{} }为什么
Tag.DataType被导出了?
我想知道的是,Tag 结构体的设计者为什么选择导出 Tag.DataType 字段。你知道吗?这是一个好的设计吗?
在Go中正确设置interface{}值的关键是确保类型断言和二进制编解码的一致性。你的实现基本正确,但可以优化类型处理部分。以下是改进后的示例:
// 使用类型转换函数简化代码
func (t *Tag) SetBytes(bytesOfValue []byte) error {
b := bytes.NewReader(bytesOfValue)
var value interface{}
var err error
switch t.DataType {
case Bit:
var v bool
err = binary.Read(b, binary.BigEndian, &v)
value = v
case Uint8:
var v uint8
err = binary.Read(b, binary.BigEndian, &v)
value = v
case Int8:
var v int8
err = binary.Read(b, binary.BigEndian, &v)
value = v
default:
return errors.New("unsupported data type")
}
if err != nil {
return fmt.Errorf("reading bytes failed: %w", err)
}
t.value = value
t.bytes = bytesOfValue
return nil
}
func (t *Tag) SetValue(value interface{}) error {
var v interface{}
switch t.DataType {
case Bit:
if val, ok := value.(bool); ok {
v = val
} else {
return errors.New("value must be bool for Bit type")
}
case Uint8:
if val, ok := value.(uint8); ok {
v = val
} else {
return errors.New("value must be uint8 for Uint8 type")
}
case Int8:
if val, ok := value.(int8); ok {
v = val
} else {
return errors.New("value must be int8 for Int8 type")
}
default:
return errors.New("unsupported data type")
}
b := new(bytes.Buffer)
if err := binary.Write(b, binary.BigEndian, v); err != nil {
return fmt.Errorf("writing bytes failed: %w", err)
}
t.bytes = b.Bytes()
t.value = value
return nil
}
// 添加获取方法确保类型安全
func (t *Tag) GetValue() interface{} {
return t.value
}
func (t *Tag) GetBytes() []byte {
return t.bytes
}
使用示例:
func main() {
t := &Tag{DataType: Int8}
// 设置值
if err := t.SetValue(int8(-128)); err != nil {
panic(err)
}
fmt.Printf("Bytes: %v, Value: %v\n", t.GetBytes(), t.GetValue())
// 设置字节
if err := t.SetBytes([]byte{128}); err != nil {
panic(err)
}
fmt.Printf("Bytes: %v, Value: %v\n", t.GetBytes(), t.GetValue())
// 类型检查示例
if val, ok := t.GetValue().(int8); ok {
fmt.Printf("Type safe value: %d\n", val)
}
}
关键改进:
- 使用fmt.Errorf包装错误以保留原始错误信息
- 为不支持的DataType添加默认错误处理
- 在SetValue中提供更明确的错误信息
- 保持二进制编解码的一致性(binary.BigEndian)
- 添加类型安全的获取方法示例
这种方法确保了interface{}值的正确设置和类型安全访问,同时保持了字节和值的同步更新。


