• Go编程-使用nil 作为函数参数需要注意
  • 发布于 2个月前
  • 114 热度
    0 评论
概述
nil 可以作为函数参数传入,这意味着函数内部逻辑处理时,不能依赖于传入的实参 (有可能是 nil), 一定要做必要的 零值 判断。

例子
示例代码只是为了演示,没有任何实质意义。

参数类型为切片
当 切片 为 nil 时,直接读取和赋值都会 panic 。
错误的做法
package main
// 堆代码 duidaima.com
// 计算前 N 个数总和
func sumTopN(numbers []int, n int) int {
    total := 0
    for _, v := range numbers[:n] {
        total += v
    }

    return total
}

func main() {
    println(sumTopN(nil, 3))
}

// $ go run main.go
// 输出如下
/**
  panic: runtime error: slice bounds out of range [:3] with capacity 0

  goroutine 1 [running]:
  ...
  ...

  exit status 2

*/
正确的做法
package main

// 计算前 N 个数总和
func sumTopN(numbers []int, n int) int {
    // 首先检测参数是否为 nil
    if n > len(numbers) {
        n = len(numbers)
    }

    total := 0
    for _, v := range numbers[:n] {
        total += v
    }

    return total
}

func main() {
    println(sumTopN(nil, 3))
}

// $ go run main.go
// 输出如下 
/**
  0
*/
参数类型为 map
当 map 为 nil 时,直接赋值会 panic 。
错误的做法
package main

// 将目标字符串计数重置为 0
func reset(counter map[string]int, target []string) {
    for _, s := range target {
        counter[s] = 0
    }
}

func main() {
    reset(nil, []string{"hello", "world"})
}

// $ go run main.go
// 输出如下
/**
  panic: assignment to entry in nil map

  goroutine 1 [running]:
  ...
  ...

  exit status 2

*/
正确的做法
package main

// 将目标字符串计数重置为 0
func reset(counter map[string]int, target []string) {
    // 首先检测参数是否为 nil
    if counter == nil {
        return
    }
    for _, s := range target {
        counter[s] = 0
    }
}

func main() {
    reset(nil, []string{"hello", "world"})
}
参数类型为指针
当 指针 为 nil 时,直接读取和赋值都会 panic 。

错误的做法
package main

import "fmt"

type person struct {
    name string
}

func setHi(p *person) {
    fmt.Printf("Hi, I'm %s", p.name)
}

func main() {
    setHi(nil)
}

// $ go run main.go
// 输出如下
/**
  panic: runtime error: invalid memory address or nil pointer dereference

  goroutine 1 [running]:
  ...
  ...

  exit status 2

*/
正确的做法
package main

import "fmt"

type person struct {
    name string
}

func setHi(p *person) {
    // 首先检测参数是否为 nil
    if p != nil {
        fmt.Printf("Hi, I'm %s", p.name)
    }
}

func main() {
    setHi(nil)
}

代码的首要目标是正确性。
用户评论