0. 概述

在编写 Go 代码的时候,由于语言的特性会遇到一些难以理解的简单错误,所以我就写了这篇文章用于记录我遇到的问题的集合。

1. mismatched types int32 and time.Duration)

今天在写一段 Go 代码的时候,居然报了一个意料之外的错:

  1. [[email protected].io]# cat test.go
  2. time.sleep(time.Second * rand.Int())

然后提示错误:

  1. invalid operation: rand.Int31n(1000) * time.Millisecond (mismatched types int32 and time.Duration)

这就很蒙了,明明:time.Second * 1 都是正常的,为什么这样不行?于是就找了找,发现需要将 int 转换成 Duration,这个没理解为什么?(updated at:2020-10-23,我在这篇文章中介绍了为什么:Go 语言中的常量

  1. [[email protected].io]# cat test.go
  2. time.Sleep(time.Second * time.Duration(rand.Int())

这样就对了。

2. string <-> float

  1. String 转换为 Float(适用于各种类型)

    1. [[email protected].io]# cat test.go
    2. f := "3.14159265"
    3. if s, err := strconv.ParseFloat(f, 32); err == nil {
    4. fmt.Println(s) // 3.1415927410125732
    5. }
    6. if s, err := strconv.ParseFloat(f, 64); err == nil {
    7. fmt.Println(s) // 3.14159265
    8. }
  2. Float 转换为 String

    1. 性能比较差的做法

      1. [[email protected].io]# cat test.go
      2. s := fmt.Sprintf("%f", 123.456) // s == "123.456000"
    2. 性能更好的做法

      1. [[email protected].io]# cat test.go
      2. strconv.FormatFloat(f, 'g', -1, 32)

3. 去除字符串中非 Ascii 字符

  1. [[email protected].io]# cat test.go
  2. func main() {
  3. example := "#GoLangCode!$!"
  4. // Make a Regex to say we only want letters and numbers
  5. reg, err := regexp.Compile("[^a-zA-Z0-9]+")
  6. if err != nil {
  7. log.Fatal(err)
  8. }
  9. processedString := reg.ReplaceAllString(example, "")
  10. fmt.Printf("A string of %s becomes %s \n", example, processedString)
  11. }

4. bytes 转为 Reader

  1. [[email protected].io]# cat test.go
  2. r := bytes.NewReader(byteData)

5. uint64 -> String

在 Go 语言中将 uint64 转换成 string 类型:

  1. [[email protected].io]# cat uint64.go
  2. var myNumber uint64
  3. myNumber = 18446744073709551615
  4. str := strconv.FormatUint(myNumber, 10)

6. Float64 的 Nan 和 Inf

注意这段代码:

  1. [[email protected].io]# cat nan.go
  2. nan := math.NaN()
  3. pos_inf := math.Inf(1)
  4. neg_inf := math.Inf(-1)
  5. fmt.Println(nan == nan) // false
  6. fmt.Println(pos_inf == pos_inf) // true
  7. fmt.Println(neg_inf == neg_inf) // true
  8. fmt.Println(pos_inf == neg_inf) // false

7. 结构体指针和非指针的差异

  1. [[email protected].io]# cat demo.go
  2. type A struct{
  3. lock sync.Mutex
  4. }
  5. pass(a A) {} // 传值,会拷贝 lock,这是不安全的
  6. for _, a := range []A{}{} // 每次迭代都会拷贝 lock,不安全
  7. for _, a := range []*A{}{} // ok 的,安全