返回

第四讲:Go语言中容易出错的场景第30-39例(数据类型及字符串)

后端

正文:

第30例:忽略nil值检查

func greet(name string) {
  if name != nil {
    fmt.Println("Hello", name)
  }
}

此函数忽略了对name变量的nil值检查,在name为nil时,程序会panic。正确的做法是显式地检查name是否为nil,如下所示:

func greet(name string) {
  if name != nil {
    fmt.Println("Hello", name)
  } else {
    fmt.Println("Hello, world")
  }
}

第31例:使用错误的type转换

var x int = 10
var y float64 = float64(x)
fmt.Println(y) // 输出: 10

在此示例中,将int类型的值转换为float64类型的值时,没有使用括号,导致编译错误。正确的做法是使用括号,如下所示:

var x int = 10
var y float64 = (float64)(x)
fmt.Println(y) // 输出: 10

第32例:将数组与切片混用

var arr [10]int
var slice = arr // 编译错误: cannot use arr (type [10]int) as type []int in assignment

在此示例中,尝试将数组arr赋值给切片slice,但数组和切片是不同的类型,因此会引发编译错误。正确的做法是使用内置的copy函数将数组的值复制到切片中,如下所示:

var arr [10]int
var slice []int = make([]int, len(arr))
copy(slice, arr[:])

第33例:使用错误的指针操作

var p *int
*p = 10 // 编译错误: invalid memory address or nil pointer dereference

在此示例中,尝试使用未初始化的指针p进行解引用,但解引用一个未初始化的指针是未定义的行为,因此会引发编译错误。正确的做法是确保指针p被初始化为有效的内存地址,如下所示:

var p *int = new(int)
*p = 10

第34例:使用错误的函数签名

func add(x, y int) int { // 编译错误: redeclared variable y
  return x + y
}

func main() {
  add(10, 20)
}

在此示例中,函数add的函数签名中重复声明了变量y,这会导致编译错误。正确的做法是确保函数签名中的变量名称是唯一的,如下所示:

func add(x, y int) int {
  return x + y
}

func main() {
  add(10, 20)
}

第35例:使用错误的切片创建方式

slice := []int{10, 20, 30} // 编译错误: cannot use {10, 20, 30} (type [3]int) as type []int in slice literal

在此示例中,使用[10, 20, 30}创建一个切片,但这种写法是错误的,因为[10, 20, 30}是一个数组,而切片和数组是不同的类型。正确的做法是使用make函数创建切片,如下所示:

slice := make([]int, 3)
slice[0] = 10
slice[1] = 20
slice[2] = 30

第36例:字符串与数字的拼接

var name string = "John"
var age int = 30
fmt.Println(name + age) // 编译错误: invalid operation: name + age (mismatched types string and int)

在此示例中,尝试将字符串name与数字age进行拼接,但字符串和数字是不同的类型,因此会引发编译错误。正确的做法是将数字age转换为字符串类型,然后再进行拼接,如下所示:

var name string = "John"
var age int = 30
fmt.Println(name + strconv.Itoa(age)) // 输出: John30

第37例:字符串比较错误

var name1 string = "John"
var name2 string = "john"
if name1 == name2 {
  fmt.Println("Names are equal")
} else {
  fmt.Println("Names are not equal")
}

// 输出: Names are not equal

在此示例中,比较字符串name1和name2时,没有考虑字符串的大小写,因此会得出错误的结论。正确的做法是使用strings.EqualFold函数比较字符串,如下所示:

var name1 string = "John"
var name2 string = "john"
if strings.EqualFold(name1, name2) {
  fmt.Println("Names are equal")
} else {
  fmt.Println("Names are not equal")
}

// 输出: Names are equal

第38例:字符串下标越界

var name string = "John"
fmt.Println(name[5]) // 编译错误: index out of range [5] with length 4

在此示例中,尝试访问字符串name的第5个字符,但字符串name只有4个字符,因此会引发编译错误。正确的做法是确保字符串索引在字符串长度的范围内,如下所示:

var name string = "John"
fmt.Println(name[3]) // 输出: n

第39例:使用错误的字符串格式化

var name string = "John"
var age int = 30
fmt.Printf("Name: %s, Age: %d", name, age) // 输出: Name: John, Age: 30

在此示例中,使用错误的格式化字符串对name和age进行格式化。正确的做法是使用正确的格式化字符串,如下所示:

var name string = "John"
var age int = 30
fmt.Printf("Name: %s, Age: %d\n", name, age) // 输出: Name: John, Age: 30