- 先上结论
golang的所有内置类型作为函数参数传递都是传值的方式(没有传递引用一说),需要注意的是:数组、slice和map作为函数参数时也是传值,但是如果对结构内元素进行的修改,修改的是原数据。如果是对其进行整体赋值,则不会修改原数据,相当于拷贝出一个新的临时变量。要想无论什么情况都修改原数据,可以通过传递指针参数实现。
- 来段实例代码
1 package main
2
3 import (
4 "bytes"
5 "fmt"
6 "strings"
7 )
8
9 func f_1(a int) {
10 a = 2
11 }
12
13 func f_1_1(a *int) {
14 *a = 2
15 }
16
17 func f_2(s string) {
18 s = "cba"
19 }
20
21 func f_2_1(s *string) {
22 *s = "cba"
23 }
24
25 func f_3(v []string) {
26 v[0] = "haha"
27 }
28
29 func f_3_1(v []string) {
30 v = nil
31 }
32
33 func f_3_2(v *[]string) {
34 *v = nil
35 }
36
37 func f_4(m map[int]int) {
38 m[1] = 3
39 m[3] = 1
40 }
41
42 func f_4_1(m map[int]int) {
43 m = nil
44 }
45
46 func f_4_2(m *map[int]int) {
47 *m = nil
48 }
49
50 func f_5(b []byte) {
51 b[0] = 0x40
52 }
53
54 func f_5_1(b []byte) {
55 b = bytes.Replace(b, []byte("1"), []byte("a"), -1)
56 }
57
58 func f_5_2(b *[]byte) {
59 *b = bytes.Replace(*b, []byte("1"), []byte("a"), -1)
60 }
61
62 type why struct {
63 s []string
64 }
65
66 func (ss why) SetV(s []string) {
67 ss.s = s
68 }
69
70 func (ss *why) SetP(s []string) {
71 ss.s = s
72 }
73
74 func (ss why) String() string {
75 return strings.Join(ss.s, ",")
76 }
77
78 func main() {
79 a := 1
80 s := "abc"
81 v := []string{"sd", "aa"}
82 m := map[int]int{1: 1, 2: 2, 3: 3}
83 f_1(a)
84 f_2(s)
85 f_3(v)
86 f_4(m)
87 fmt.Printf("%d,%s,%v,%v\n", a, s, v, m)
88 f_3_1(v)
89 f_4_1(m)
90 fmt.Printf("%d,%s,%v,%v\n", a, s, v, m)
91 f_1_1(&a)
92 f_2_1(&s)
93 f_3_2(&v)
94 f_4_2(&m)
95 fmt.Printf("%d,%s,%v,%v\n", a, s, v, m)
96 b := []byte("12145178")
97 f_5(b)
98 fmt.Printf("%s\n", b)
99 f_5_1(b)
100 fmt.Printf("%s\n", b)
101 f_5_2(&b)
102 fmt.Printf("%s\n", b)
103 ss := &why{}
104 ss.SetV([]string{"abc", "efg"})
105 fmt.Println(ss)
106 ss.SetP([]string{"abc", "efg"})
107 fmt.Println(ss)
108 }
输出如下
1 1,abc,[haha aa],map[1:3 2:2 3:1] slice和map值传递是可以修改原数据的,但基本数据类型不行 2 1,abc,[haha aa],map[1:3 2:2 3:1] 整体赋值不会修改原数据,值得注意的是map是无序的 3 2,cba,[],map[] 传递指针始终会修改原数据 4 @2145178 同上 5 @2145178 使用bytes.Replace实际上还是赋值,所以不会修改原数据 6 @2a45a78 使用指针传参就可以了 7 类的成员函数定义为传值的方式,不会修改原数据(原数据为空) 8 abc,efg 类的成员函数定义为传指针的方式,可以修改原成员变量 9 10 成功: 进程退出代码 0.
现在弄明白了吗~