golang简化基本类型可选字段创建的辅助工具插件库pointer的使用
Golang简化基本类型可选字段创建的辅助工具插件库pointer的使用
概述
pointer是一个帮助简化创建基本类型可选字段的Golang工具库。它提供了一系列辅助函数来创建各种基本类型的指针,使得在结构体字面量或变量中设置指针类型字段变得更加方便。
安装
go get github.com/xorcare/pointer
使用泛型(Go 1.18+)
从Go 1.18开始,你可以使用Of
方法来获取任何类型值的指针:
package pointer
// Of是一个辅助函数,分配一个新的any值来存储v并返回其指针
func Of[Value any](v Value) *Value {
return &v
}
完整示例
package main
import (
"fmt"
"time"
"github.com/xorcare/pointer"
)
type Config struct {
Enabled *bool
Timeout *time.Duration
Port *int
Name *string
}
func main() {
// 使用pointer库创建配置
config := Config{
Enabled: pointer.Bool(true),
Timeout: pointer.Duration(30 * time.Second),
Port: pointer.Int(8080),
Name: pointer.String("my-app"),
}
// 打印配置
fmt.Printf("Enabled: %v\n", *config.Enabled)
fmt.Printf("Timeout: %v\n", *config.Timeout)
fmt.Printf("Port: %d\n", *config.Port)
fmt.Printf("Name: %s\n", *config.Name)
}
常见问题解答
问题 | 示例代码 |
---|---|
如何在结构体字面量或变量中设置bool指针? | var _ *bool = pointer.Bool(true) |
如何在结构体字面量或变量中设置byte指针? | var _ *byte = pointer.Byte(1) |
如何在结构体字面量或变量中设置complex64指针? | var _ *complex64 = pointer.Complex64(1.1) |
如何在结构体字面量或变量中设置complex128指针? | var _ *complex128 = pointer.Complex128(1.1) |
如何在结构体字面量或变量中设置float32指针? | var _ *float32 = pointer.Float32(1.1) |
如何在结构体字面量或变量中设置float64指针? | var _ *float64 = pointer.Float64(1.1) |
如何在结构体字面量或变量中设置int指针? | var _ *int = pointer.Int(1) |
如何在结构体字面量或变量中设置int8指针? | var _ *int8 = pointer.Int8(8) |
如何在结构体字面量或变量中设置int16指针? | var _ *int16 = pointer.Int16(16) |
如何在结构体字面量或变量中设置int32指针? | var _ *int32 = pointer.Int32(32) |
如何在结构体字面量或变量中设置int64指针? | var _ *int64 = pointer.Int64(64) |
如何在结构体字面量或变量中设置rune指针? | var _ *rune = pointer.Rune(1) |
如何在结构体字面量或变量中设置string指针? | var _ *string = pointer.String("ptr") |
如何在结构体字面量或变量中设置uint指针? | var _ *uint = pointer.Uint(1) |
如何在结构体字面量或变量中设置uint8指针? | var _ *uint8 = pointer.Uint8(8) |
如何在结构体字面量或变量中设置uint16指针? | var _ *uint16 = pointer.Uint16(16) |
如何在结构体字面量或变量中设置uint32指针? | var _ *uint32 = pointer.Uint32(32) |
如何在结构体字面量或变量中设置uint64指针? | var _ *uint64 = pointer.Uint64(64) |
如何在结构体字面量或变量中设置time.Time指针? | var _ *time.Time = pointer.Time(time.Now()) |
如何在结构体字面量或变量中设置time.Duration指针? | var _ *time.Duration = pointer.Duration(time.Hour) |
替代方案
作者建议,对于Go 1.18+项目,可以考虑在项目中创建一个本地副本而不是依赖这个库。例如,可以在internal/pointer/pointer.go
文件中添加以下代码:
package pointer
// Of是一个辅助函数,分配一个新的any值来存储v并返回其指针
func Of[Value any](v Value) *Value {
return &v
}
许可证
© 2019-2020,2022 Vasiliy Vasilyuk
基于BSD 3-Clause许可证发布。
更多关于golang简化基本类型可选字段创建的辅助工具插件库pointer的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于golang简化基本类型可选字段创建的辅助工具插件库pointer的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
Golang 可选字段辅助工具 - pointer 库使用指南
在 Go 语言中,处理可选字段时通常需要使用指针类型,但直接使用指针语法会让代码变得冗长。pointer
库是一个简化基本类型可选字段创建的辅助工具,它可以帮助我们更简洁地创建基本类型的指针。
安装 pointer 库
go get github.com/AlekSi/pointer
基本使用方法
pointer
库提供了 To
系列函数来创建各种基本类型的指针:
package main
import (
"fmt"
"github.com/AlekSi/pointer"
)
func main() {
// 创建各种基本类型的指针
intPtr := pointer.ToInt(42)
floatPtr := pointer.ToFloat64(3.14)
stringPtr := pointer.ToString("hello")
boolPtr := pointer.ToBool(true)
fmt.Println(*intPtr) // 输出: 42
fmt.Println(*floatPtr) // 输出: 3.14
fmt.Println(*stringPtr) // 输出: hello
fmt.Println(*boolPtr) // 输出: true
}
主要功能
1. 创建指针
pointer
库支持所有基本类型的指针创建:
// 整数类型
i8 := pointer.ToInt8(8)
i16 := pointer.ToInt16(16)
i32 := pointer.ToInt32(32)
i64 := pointer.ToInt64(64)
// 无符号整数类型
u8 := pointer.ToUint8(8)
u16 := pointer.ToUint16(16)
u32 := pointer.ToUint32(32)
u64 := pointer.ToUint64(64)
// 浮点数
f32 := pointer.ToFloat32(3.14)
f64 := pointer.ToFloat64(3.1415926)
// 其他类型
str := pointer.ToString("golang")
b := pointer.ToBool(true)
t := pointer.ToTime(time.Now())
2. 获取指针值或默认值
package main
import (
"fmt"
"github.com/AlekSi/pointer"
)
func main() {
var nilInt *int
// 获取指针值,如果为nil则返回默认值
v1 := pointer.GetInt(nilInt) // 返回 0
v2 := pointer.GetInt(nilInt, 42) // 返回 42
fmt.Println(v1, v2)
}
3. 比较指针值
package main
import (
"fmt"
"github.com/AlekSi/pointer"
)
func main() {
a := pointer.ToInt(10)
b := pointer.ToInt(10)
c := pointer.ToInt(20)
fmt.Println(pointer.Equal(a, b)) // true
fmt.Println(pointer.Equal(a, c)) // false
}
4. 解引用指针
package main
import (
"fmt"
"github.com/AlekSi/pointer"
)
func main() {
var nilInt *int
val := pointer.Deref(nilInt, 100) // 如果nilInt为nil,返回100
fmt.Println(val) // 输出: 100
}
实际应用示例
结构体中的可选字段
package main
import (
"fmt"
"github.com/AlekSi/pointer"
)
type User struct {
ID int
Name string
Age *int // 可选字段
IsActive *bool // 可选字段
LastLogin *string // 可选字段
}
func main() {
// 创建用户,只设置必填字段
user1 := User{
ID: 1,
Name: "Alice",
}
// 创建用户,设置所有字段
user2 := User{
ID: 2,
Name: "Bob",
Age: pointer.ToInt(30),
IsActive: pointer.ToBool(true),
LastLogin: pointer.ToString("2023-01-01"),
}
fmt.Printf("%+v\n", user1)
fmt.Printf("%+v\n", user2)
// 安全访问可选字段
age := pointer.GetInt(user1.Age, -1) // 返回-1,因为Age是nil
fmt.Println("Alice's age:", age)
}
JSON 序列化/反序列化
package main
import (
"encoding/json"
"fmt"
"github.com/AlekSi/pointer"
)
type Config struct {
Host string
Port *int `json:"port,omitempty"`
Timeout *int `json:"timeout,omitempty"`
Debug *bool `json:"debug,omitempty"`
}
func main() {
// 序列化
cfg := Config{
Host: "localhost",
Port: pointer.ToInt(8080),
Debug: pointer.ToBool(false),
// Timeout 保持nil
}
data, _ := json.MarshalIndent(cfg, "", " ")
fmt.Println(string(data))
// 反序列化
jsonStr := `{"host":"example.com","timeout":30}`
var cfg2 Config
json.Unmarshal([]byte(jsonStr), &cfg2)
fmt.Printf("%+v\n", cfg2)
fmt.Println("Port is set:", cfg2.Port != nil) // false
fmt.Println("Timeout:", pointer.GetInt(cfg2.Timeout)) // 30
}
总结
pointer
库的主要优点:
- 简化了基本类型指针的创建语法
- 提供了安全的指针解引用方法
- 支持指针值的比较
- 特别适合处理结构体中的可选字段
- 与 JSON 序列化/反序列化配合良好
相比直接使用 &
操作符创建指针,pointer
库的代码更清晰易读,特别是在处理大量可选字段时能显著提高代码的可维护性。