英文:
A good way to make zero value meaningful
问题
我有一个结构体,其中包含一个int16,表示切片中索引的偏移量。这个值有两种状态:1. 偏移量无效;2. 有意义且实际上表示一个正数、负数或零值的偏移量。现在的问题是,我将分配一个包含此结构体的数组,而这个int16的默认值应该是无效状态,但默认值是0,而0也可以表示一个值为0的有效偏移量。
目前,我使用-32768作为表示无效状态的值,并在使用make
之后手动初始化数组。然而,我不喜欢这种方法,它不符合Go语言中让零值有意义的方式。有没有更好的方法来解决这个问题?我真的不想引入额外的变量,因为那会占用更多的内存空间。
英文:
I have a struct with a int16 in it represent the offset of indexes in a slice. There are 2 states for this value: 1. it can be that the offset is invalid; 2. it's meaningful and will actually represent a positive, negative, or zero value offset. Now the question is that I will allocate an array of this struct, and the default value for this int16 should be the invalid state, but the default value is 0, and 0 can also represent a valid offset with value of 0.
Currently, I use -32768 as the value to represent the invalid state, and manually initialize the array after using make
. However, I don't like this approach and it doesn't follow the Go way of making the zero value meaningful. Is there a better way to approach this? I don't really want to introduce extra variables as that will take more space in memory.
答案1
得分: 1
当访问偏移值时,可以通过加法和减法将零值重新映射为无效常量。这将需要通过Get
和Set
来隐藏类型,因为直接访问内部值将不再有效。
package main
import "fmt"
type Offset struct {
// This value is not safe to use directly,
// since it has to be mapped to/from a real offset
mappedOffset int16
}
const InvalidOffset = -32768
func (o Offset) Get() int16 {
// Shift values so 0 becomes InvalidOffset
return o.mappedOffset + InvalidOffset
}
func (o *Offset) Set(i int16) {
// Shift values so InvalidOffset becomes 0
o.mappedOffset = i - InvalidOffset
}
func (o Offset) IsValid() bool {
// Check if it is the actual "Go Zero"
return o != Offset{}
}
func main() {
var offset Offset
fmt.Println("Apparent value:", offset.Get(), " Internal:", offset, " IsValid:", offset.IsValid())
offset.Set(123)
fmt.Println("Apparent value:", offset.Get(), " Internal:", offset, " IsValid:", offset.IsValid())
offset.Set(InvalidOffset)
fmt.Println("Apparent value:", offset.Get(), " Internal:", offset, " IsValid:", offset.IsValid())
}
输出:
Apparent value: -32768 Internal: {0} IsValid: false
Apparent value: 123 Internal: {-32645} IsValid: true
Apparent value: -32768 Internal: {0} IsValid: false
英文:
When accessing the offset value, you can remap the zero value to the invalid constant through addition and subtraction. This will require obscuring the type through a Get
and Set
, since accessing the internal value directly will no longer be valid.
package main
import "fmt"
type Offset struct {
// This value is not safe to use directly,
// since it has to be mapped to/from a real offset
mappedOffset int16
}
const InvalidOffset = -32768
func (o Offset) Get() int16 {
// Shift values so 0 becomes InvalidOffset
return o.mappedOffset + InvalidOffset
}
func (o *Offset) Set(i int16) {
// Shift values so InvalidOffset becomes 0
o.mappedOffset = i - InvalidOffset
}
func (o Offset) IsValid() bool {
// Check if it is the actual "Go Zero"
return o != Offset{}
}
func main() {
var offset Offset
fmt.Println("Apparent value:", offset.Get(), " Internal:", offset, " IsValid:", offset.IsValid())
offset.Set(123)
fmt.Println("Apparent value:", offset.Get(), " Internal:", offset, " IsValid:", offset.IsValid())
offset.Set(InvalidOffset)
fmt.Println("Apparent value:", offset.Get(), " Internal:", offset, " IsValid:", offset.IsValid())
}
Output:
Apparent value: -32768 Internal: {0} IsValid: false
Apparent value: 123 Internal: {-32645} IsValid: true
Apparent value: -32768 Internal: {0} IsValid: false
答案2
得分: 0
找到了一个解决方案。我可以使用一个uint16来存储它,并用math.minint16进行偏移。这样,默认值0就是-32768,并被视为无效状态,其他所有数字都是有效的。
英文:
Found a solution. I can store it using an uint16 and offset it with math.minint16. This way the default value 0 is -32768 and is treated as the invalid state, all other numbers are valid.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论