让零值有意义的好方法

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

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来隐藏类型,因为直接访问内部值将不再有效。

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.

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:

确定