如何在golang结构中使用bit而不是bool?
How to use bit instead of bool in golang structure?
type EventPrefs struct {
Call bool
Presence bool
Endpoint bool
VoiceMail bool
CallRecording bool
}
目前,该结构类型的大小是 5 个字节,但我想使用位。有什么办法吗?
Go中没有“bit”类型,所以如果要将多个bool
信息打包成bit,就得自己实现了。声明类型为 uint8
(或 uint16
或任何其他整数类型)的字段,并提供获取/设置字段特定位的方法。
一般的位设置/清除就这么简单:
var masks = []uint8{0x01, 0x02, 0x04, 0x08, 0x10}
func set(field, data uint8, b bool) uint8 {
if b {
return data | masks[field] // Set bit
}
return data ^ masks[field] // Clear bit
}
func get(field, data uint8) bool {
return data&masks[field] != 0
}
将您的 5 个布尔字段打包成一个 uint8
值:
type EventPrefs struct {
data uint8
}
func (e *EventPrefs) SetCall(b bool) { e.data = set(0, e.data, b) }
func (e *EventPrefs) Call() bool { return get(0, e.data) }
func (e *EventPrefs) SetPresence(b bool) { e.data = set(1, e.data, b) }
func (e *EventPrefs) Presence() bool { return get(1, e.data) }
func (e *EventPrefs) SetEndpoint(b bool) { e.data = set(2, e.data, b) }
func (e *EventPrefs) Endpoint() bool { return get(2, e.data) }
func (e *EventPrefs) SetVoiceMail(b bool) { e.data = set(3, e.data, b) }
func (e *EventPrefs) VoiceMail() bool { return get(3, e.data) }
func (e *EventPrefs) SetCallRecording(b bool) { e.data = set(4, e.data, b) }
func (e *EventPrefs) CallRecording() bool { return get(4, e.data) }
正在测试:
ep := &EventPrefs{}
fmt.Println("Calls:", ep.Call(), ep.data)
ep.SetCall(true)
fmt.Println("Calls:", ep.Call(), ep.data)
fmt.Println("Presence:", ep.Presence(), ep.data)
ep.SetPresence(true)
fmt.Println("Presence:", ep.Presence(), ep.data)
ep.SetPresence(false)
fmt.Println("Presence:", ep.Presence(), ep.data)
哪些输出(在 Go Playground 上尝试):
Calls: false 0
Calls: true 1
Presence: false 1
Presence: true 3
Presence: false 1
节省 4 个字节值得这么麻烦吗?很少。
注意:上述解决方案可以有多种变体。例如,可以使用移位“计算”掩码,set()
和 get()
函数可以是 EventPrefs
的方法,因此不需要 data
参数(并且 set()
可以直接设置 EventPrefs.data
字段,因此也不需要 return 值)。如果 set()
仍然是一个函数,那么 data
参数可以是一个指针,因此 set()
可以更改指向的值而无需 return 新的 data
等。data
字段可能有自己的声明类型,例如bitpack
附有 get()
和 set()
方法。
查看相关:
type EventPrefs struct {
Call bool
Presence bool
Endpoint bool
VoiceMail bool
CallRecording bool
}
目前,该结构类型的大小是 5 个字节,但我想使用位。有什么办法吗?
Go中没有“bit”类型,所以如果要将多个bool
信息打包成bit,就得自己实现了。声明类型为 uint8
(或 uint16
或任何其他整数类型)的字段,并提供获取/设置字段特定位的方法。
一般的位设置/清除就这么简单:
var masks = []uint8{0x01, 0x02, 0x04, 0x08, 0x10}
func set(field, data uint8, b bool) uint8 {
if b {
return data | masks[field] // Set bit
}
return data ^ masks[field] // Clear bit
}
func get(field, data uint8) bool {
return data&masks[field] != 0
}
将您的 5 个布尔字段打包成一个 uint8
值:
type EventPrefs struct {
data uint8
}
func (e *EventPrefs) SetCall(b bool) { e.data = set(0, e.data, b) }
func (e *EventPrefs) Call() bool { return get(0, e.data) }
func (e *EventPrefs) SetPresence(b bool) { e.data = set(1, e.data, b) }
func (e *EventPrefs) Presence() bool { return get(1, e.data) }
func (e *EventPrefs) SetEndpoint(b bool) { e.data = set(2, e.data, b) }
func (e *EventPrefs) Endpoint() bool { return get(2, e.data) }
func (e *EventPrefs) SetVoiceMail(b bool) { e.data = set(3, e.data, b) }
func (e *EventPrefs) VoiceMail() bool { return get(3, e.data) }
func (e *EventPrefs) SetCallRecording(b bool) { e.data = set(4, e.data, b) }
func (e *EventPrefs) CallRecording() bool { return get(4, e.data) }
正在测试:
ep := &EventPrefs{}
fmt.Println("Calls:", ep.Call(), ep.data)
ep.SetCall(true)
fmt.Println("Calls:", ep.Call(), ep.data)
fmt.Println("Presence:", ep.Presence(), ep.data)
ep.SetPresence(true)
fmt.Println("Presence:", ep.Presence(), ep.data)
ep.SetPresence(false)
fmt.Println("Presence:", ep.Presence(), ep.data)
哪些输出(在 Go Playground 上尝试):
Calls: false 0
Calls: true 1
Presence: false 1
Presence: true 3
Presence: false 1
节省 4 个字节值得这么麻烦吗?很少。
注意:上述解决方案可以有多种变体。例如,可以使用移位“计算”掩码,set()
和 get()
函数可以是 EventPrefs
的方法,因此不需要 data
参数(并且 set()
可以直接设置 EventPrefs.data
字段,因此也不需要 return 值)。如果 set()
仍然是一个函数,那么 data
参数可以是一个指针,因此 set()
可以更改指向的值而无需 return 新的 data
等。data
字段可能有自己的声明类型,例如bitpack
附有 get()
和 set()
方法。
查看相关: