第四讲:Go语言中容易出错的场景第30-39例(数据类型及字符串)
2023-12-15 17:57:04
正文:
第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