golang内置数据类型作为函数参数

  • 先上结论

  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
", a, s, v, m)
 88     f_3_1(v)
 89     f_4_1(m)
 90     fmt.Printf("%d,%s,%v,%v
", 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
", a, s, v, m)
 96     b := []byte("12145178")
 97     f_5(b)
 98     fmt.Printf("%s
", b)
 99     f_5_1(b)
100     fmt.Printf("%s
", b)
101     f_5_2(&b)
102     fmt.Printf("%s
", 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.

现在弄明白了吗~

原文地址:https://www.cnblogs.com/borey/p/5622820.html