func main() { e := newExample(233) fmt.Printf("e=%v, type=%T\n", e, e) } type Example []byte func (b Example) String() string { return fmt.Sprintf("Example(%d KB)", len(b)/1024) } func newExample(size int) *Example { b := make([]byte, size*1024) for i := range size { b[i] = byte(i) % 255 } return (*Example)(&b) }如果我们希望在 Example 被垃圾回收时运行一个清理函数,现在可以直接借用 runtime.AddCleanup 就可以很便捷的达到目的了。
func cleanup(created time.Time) { fmt.Printf( "object is cleaned up! lifetime = %dms\n", time.Since(created)/time.Millisecond, ) } func main() { e := newExample(233) // 堆代码 duidaima.com now := time.Now() runtime.AddCleanup(e, cleanup, now) time.Sleep(10 * time.Millisecond) e = nil runtime.GC() time.Sleep(10 * time.Millisecond) }输出结果:
object is cleaned up! lifetime = 10ms可以看到该函数顺利在 newExample 结束后进行垃圾回收时运行了提前注册的函数。
func main() { log := slog.New( slog.NewTextHandler(io.Discard, nil), ) log.Info("堆代码 duidaima.com") }现在新版本后,代码直接这么写即可:
func main() { log := slog.New(slog.DiscardHandler) log.Info("脑子进煎鱼了!") }增加 strings 标准库迭代器方法
strings.LinesLines 函数签名:
func Lines(s string) iter.Seq[string]Lines 返回字符串 s 中换行结束行 \n 的迭代器。如果 s 为空,则迭代器不会产生任何行。如果 s 不以换行结束,则最后生成的行也不会以换行结束。
func main() { s := "脑子\n进\n煎鱼了" for line := range strings.Lines(s) { fmt.Print(line) } }输出结果:
func SplitSeq(s, sep string) iter.Seq[string]SplitSeq 返回用 sep 分隔的 s 的所有子串的迭代器。该迭代器产生的字符串与 Split(s, sep) 返回的字符串相同,但不构造切片。
func main() { s := "脑子-进-煎鱼了" for part := range strings.SplitSeq(s, "-") { fmt.Println(part) } }输出结果:
煎鱼了
func SplitAfterSeq(s, sep string) iter.Seq[string]SplitAfterSeq 返回在每个 sep 实例之后分割的 s 子串的迭代器。该迭代器产生的字符串与 SplitAfter(s, sep) 返回的字符串相同,但不需要构造切片。
func main() { s := "脑子-进-煎鱼了" for part := range strings.SplitAfterSeq(s, "-") { fmt.Println(part) } }输出结果:
煎鱼了
func FieldsSeq(s string) iter.Seq[string]根据 unicode.IsSpace 的定义,FieldsSeq 返回围绕空白字符串分割的 s 子串的迭代器。迭代器产生的字符串与 Fields(s) 返回的字符串相同,但不需要构建切片。
func main() { s := "脑子 进\n煎鱼了" for part := range strings.FieldsSeq(s) { fmt.Println(part) } }输出结果:
煎鱼了
func FieldsFuncSeq(s string, f func(rune) bool) iter.Seq[string]FieldsFuncSeq 返回围绕满足 f(c) 的 Unicode 代码点运行分割的 s 子串的迭代器。迭代器产生的字符串与 FieldsFunc(s) 返回的字符串相同,但不需要构建切片。
func main() { f := func(c rune) bool { return !unicode.IsLetter(c) && !unicode.IsNumber(c) } s := "脑子,进;煎鱼了..." for part := range strings.FieldsFuncSeq(s, f) { fmt.Println(part) } }输出结果:
煎鱼了
type Person struct { Name string `json:"name"` BirthDate time.Time `json:"birth_date,omitempty"` } func main() { eddycjy := Person{Name: "煎鱼"} b, err := json.Marshal(eddycjy) fmt.Println(string(b), err) }输出结果:
{"name":"煎鱼","birth_date":"0001-01-01T00:00:00Z"} <nil>可以看到 birth_date 是有零值结果的。
type Person struct { Name string `json:"name"` BirthDate time.Time `json:"birth_date,omitzero"` } func main() { eddycjy := Person{Name: "煎鱼"} b, err := json.Marshal(eddycjy) fmt.Println(string(b), err) }输出结果:
{"name":"煎鱼"} <nil>可以看到 JSON 后 birth_date 的零值没有了。只有 name 的值结果。符合使用预期。