让零值有意义的好方法

huangapple go评论108阅读模式
英文:

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

当访问偏移值时,可以通过加法和减法将零值重新映射为无效常量。这将需要通过GetSet来隐藏类型,因为直接访问内部值将不再有效。

  1. package main
  2. import "fmt"
  3. type Offset struct {
  4. // This value is not safe to use directly,
  5. // since it has to be mapped to/from a real offset
  6. mappedOffset int16
  7. }
  8. const InvalidOffset = -32768
  9. func (o Offset) Get() int16 {
  10. // Shift values so 0 becomes InvalidOffset
  11. return o.mappedOffset + InvalidOffset
  12. }
  13. func (o *Offset) Set(i int16) {
  14. // Shift values so InvalidOffset becomes 0
  15. o.mappedOffset = i - InvalidOffset
  16. }
  17. func (o Offset) IsValid() bool {
  18. // Check if it is the actual "Go Zero"
  19. return o != Offset{}
  20. }
  21. func main() {
  22. var offset Offset
  23. fmt.Println("Apparent value:", offset.Get(), " Internal:", offset, " IsValid:", offset.IsValid())
  24. offset.Set(123)
  25. fmt.Println("Apparent value:", offset.Get(), " Internal:", offset, " IsValid:", offset.IsValid())
  26. offset.Set(InvalidOffset)
  27. fmt.Println("Apparent value:", offset.Get(), " Internal:", offset, " IsValid:", offset.IsValid())
  28. }

输出:

  1. Apparent value: -32768 Internal: {0} IsValid: false
  2. Apparent value: 123 Internal: {-32645} IsValid: true
  3. 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.

  1. package main
  2. import "fmt"
  3. type Offset struct {
  4. // This value is not safe to use directly,
  5. // since it has to be mapped to/from a real offset
  6. mappedOffset int16
  7. }
  8. const InvalidOffset = -32768
  9. func (o Offset) Get() int16 {
  10. // Shift values so 0 becomes InvalidOffset
  11. return o.mappedOffset + InvalidOffset
  12. }
  13. func (o *Offset) Set(i int16) {
  14. // Shift values so InvalidOffset becomes 0
  15. o.mappedOffset = i - InvalidOffset
  16. }
  17. func (o Offset) IsValid() bool {
  18. // Check if it is the actual "Go Zero"
  19. return o != Offset{}
  20. }
  21. func main() {
  22. var offset Offset
  23. fmt.Println("Apparent value:", offset.Get(), " Internal:", offset, " IsValid:", offset.IsValid())
  24. offset.Set(123)
  25. fmt.Println("Apparent value:", offset.Get(), " Internal:", offset, " IsValid:", offset.IsValid())
  26. offset.Set(InvalidOffset)
  27. fmt.Println("Apparent value:", offset.Get(), " Internal:", offset, " IsValid:", offset.IsValid())
  28. }

Output:

  1. Apparent value: -32768 Internal: {0} IsValid: false
  2. Apparent value: 123 Internal: {-32645} IsValid: true
  3. 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.

huangapple
  • 本文由 发表于 2023年2月10日 04:58:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/75404351.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定