go基础第四篇:常见开发错误
1、入参数组修改不了
一个无返回值的函数,入参是一个基本数据类型的数组,在函数中修改数组的值,是不会生效的。想要生效,需要把入参由数组改为数组指针或者slice。
如果数组的元素不是基本数据类型,而是自定义的struct类型,那么除了把入参由数组改为数组指针或者slice外,把入参由普通数组改成指针数组也行。
func f(s [5]int) {
for i := range s {
s[i] = 10
}
}
func main() {
s := [5]int{1, 2, 3, 4, 5}
fmt.Println(s)
f(s)
fmt.Println(s)
}
上例中,第二次打印s依旧会打印出[1 2 3 4 5]。
把入参由基本类型数组改为基本类型数组的指针,对数组的改动会生效:
func f(s *[5]int) {
for i := range s {
s[i] = 10
}
}
func main() {
s := [5]int{1, 2, 3, 4, 5}
fmt.Println(s)
f(&s)
fmt.Println(s)
}
上例中,第二次打印s会打印出[10 10 10 10 10]。
把入参由基本类型数组改为基本类型切片,对切片的改动也会生效:
func f(s []int) {
for i := range s {
s[i] = 10
}
}
func main() {
s := []int{1, 2, 3, 4, 5}
fmt.Println(s)
f(s)
fmt.Println(s)
}
上例中,第二次打印s会打印出[10 10 10 10 10]。
即使数组的元素是自定义的struct类型,对数组的改动也不会生效:
type Person struct {
Name string
Age int
}
func f(s [2]Person) {
for i := range s {
s[i].Age = 30
}
}
func main() {
p1 := Person{Name: "John", Age: 18}
p2 := Person{Name: "Jane", Age: 25}
s := [2]Person{p1, p2}
fmt.Println(s)
f(s)
fmt.Println(s)
}
上例中,第二次打印s依旧会打印出[{John 18} {Jane 25}]。
把入参由普通数组改成指针数组,对数组的改动会生效:
type Person struct {
Name string
Age int
}
func f(s [2]*Person) {
for i := range s {
s[i].Age = 30
}
}
func main() {
p1 := &Person{Name: "John", Age: 18}
p2 := &Person{Name: "Jane", Age: 25}
s := [2]*Person{p1, p2}
fmt.Println(s)
f(s)
for _, e := range s {
fmt.Println(e)
}
}
2、入参slice append不了
一个无返回值的函数,入参是一个slice,在函数中调用append函数给slice添加数据。函数执行完后,打印该slice,发现slice并没有变化,不管slice的元素类型是指针类型还是非指针类型,都不行。想要生效,需要把入参由slice改为slice指针。
函数入参是slice,在函数中append不生效:
type Person struct {
Name string
Age int
}
func f(s []Person) {
s = append(s, Person{"Molly", 20})
}
func main() {
p1 := Person{Name: "John", Age: 18}
p2 := Person{Name: "Jane", Age: 25}
s := []Person{p1, p2}
fmt.Println(s)
f(s)
fmt.Println(s)
}
上例中,第二次打印s依旧会打印出[{John 18} {Jane 25}]。
把入参由slice改为slice指针,会发现有变化:
type Person struct { Name string Age int } func f(s *[]Person) { *s = append(*s, Person{"Molly", 20}) } func main() { p1 := Person{Name: "John", Age: 18} p2 := Person{Name: "Jane", Age: 25} s := []Person{p1, p2} fmt.Println(s) f(&s) fmt.Println(s) }
上例中,第二次打印s会打印出[{John 18} {Jane 25} {Molly 20}]。
3、在函数中修改struct slice中元素的属性不生效
type Person struct {
Name string
Age int
}
func f(s []Person) {
for _, e := range s {
e.Age = 30
}
}
func main() {
p1 := Person{Name: "John", Age: 18}
p2 := Person{Name: "Jane", Age: 25}
s := []Person{p1, p2}
fmt.Println(s)
f(s)
fmt.Println(s)
}
修复方案有三种:
第一种:把修改struct slice元素属性的函数改为用range表达式的索引取元素,而不是直接从range表达式取元素,如下:
func f(s []Person) {
for i := range s {
s[i].Age = 30
}
}
第二种:把修改struct slice元素属性的函数改为用for i := 0; i < len(s); i++,进而通过索引取元素,如下:
func f(s []Person) { for i := 0; i < len(s); i++ { s[i].Age = 30 } }
第三种:把struct slice改为struct指针数组,如下:
type Person struct {
Name string
Age int
}
func f(s []*Person) {
for _, e := range s {
e.Age = 30
}
}
func main() {
p1 := &Person{Name: "John", Age: 18}
p2 := &Person{Name: "Jane", Age: 25}
s := []*Person{p1, p2}
fmt.Println(s[0])
f(s)
fmt.Println(s[0])
}
由于自己之前不知道前两种方案,所以在项目中用的是第三种方案。
浙公网安备 33010602011771号