您的位置:首页 > 编程语言 > Go语言

go里基本数据、结构体、map、数组中值传递与地址传递分析

2017-12-11 11:47 597 查看
int类型的值传递与地值传递的两段代码:

package main

import (
"fmt"
)

func main() {
age := 15
fmt.Println("原地址:")
fmt.Println(&age)
fmt.Println("值传递地址:")
method(age)
fmt.Println("指针传递地址:")
method1(&age)
}

func method(age int) {
fmt.Println(&age)
}

func method1(age *int) {
fmt.Println(age)
}

打印结果为:
1
6

package main

import (
"fmt"
)

func main() {
age := 15
fmt.Println("原地址:")
fmt.Println(&age)
fmt.Println("值传递地址:")
method(age)
fmt.Println("指针传递地址:")
method1(&age)
}

func method(age int) {
fmt.Println(&age)
}

func method1(age *int) {
fmt.Println(age)
}

打印的结果如下:
原地址:
0xc04203c1d0
值传递地址:
0xc04203c1d8
指针传递地址:
0xc04203c1d0
结合两个例子打印的值与地址信息,可以看出int类型在值传递的时候是重新分配一个值过去,并不会改变原有的值,地址传递时是直接把当前的地址传过去,可以直接改变原有的值。

结构体类型的值传递与地值传递的两段代码:

package main

import (
"fmt"
)

type person struct {
age  int
name string
}

func main() {
per := person{
age:  15,
name: "jerry",
}
fmt.Println("值传递之前的信息:")
fmt.Println(per)
struct_method(per)
fmt.Println("值传递之后的信息:")
fmt.Println(per)

per2 := person{
age:  16,
name: "dalianmao",
}
fmt.Println("地址传递之前的信息:")
fmt.Println(per2)
struct_method1(&per2)
fmt.Println("地址传递之后的信息:")
fmt.Println(per2)
}
func struct_method1(per *person) {
per.age = 21
per.name = "taoqi"
}
func struct_method(per person) {
per.age = 20
per.name = "tom"
}

结果是:
值传递之前的信息:
{15 jerry}
值传递之后的信息:
{15 jerry}
地址传递之前的信息:
{16 dalianmao}
地址传递之后的信息:
{21 taoqi}

package main

import (
"fmt"
)

type person struct {
age  int
name string
}

func main() {
per := person{
age:  15,
name: "jerry",
}
fmt.Println(fmt.Sprintf("值传递之前的地址为:%p", &per))

dizhi(per)
dizhi1(&per)
}
func dizhi(per person) {
fmt.Println(fmt.Sprintf("值传递的地址为:%p", &per))
}
func dizhi1(per *person) {
fmt.Println(fmt.Sprintf("地址传递的地址为:%p", per))
}

结果是:
值传递之前的地址为:0xc042042400
值传递的地址为:0xc042042460
地址传递的地址为:0xc042042400

结合两个例子打印的值与地址信息,可见结构体类型值传递并不能改变结构体的信息,只有地址传递过可以,说明即便是结构体在值传递的时候也是复制一份传递过去。

package main

import (
"fmt"
)

func main() {
array := []int{1}
fmt.Println(array)
methodArrayValue(array)
fmt.Println(array)
methodArrayValue1(&array)
fmt.Println(array)
}
func methodArrayValue(array []int) {
array = append(array, 2)
}
func methodArrayValue1(array *[]int) {
*array = append(*array, 3)
}

结果是:
[1]
[1]
[1 3]

package main

import (
"fmt"
)

func main() {
array := []int{1}
fmt.Println(fmt.Sprintf("传递之前的地址为:%p", &array))
methodArrayValue(array)
methodArrayValue1(&array)
}
func methodArrayValue(array []int) {
fmt.Println(fmt.Sprintf("值传传递的地址为:%p", &array))
}
func methodArrayValue1(array *[]int) {
fmt.Println(fmt.Sprintf("地址传递的地址为:%p", array))
}

结合两个例子打印的值与地址信息,可见数组在值传递时使用的也是重新复制一个数组传过去,而地址传递的时候直接把地址传了过去。

map的值传递与地址传递

package main

import (
"fmt"
)

func main() {
infos := map[string]string{
"a": "A",
}
methodArrayValue(infos)
fmt.Println(infos)
methodArrayValue1(&infos)
fmt.Println(infos)
}
func methodArrayValue(infos map[string]string) {
infos["b"] = "B"
}
func methodArrayValue1(infos *map[string]string) {
(*infos)["c"] = "C"
}

打印结果是:
map[b:B a:A]
map[c:C a:A b:B]

package main

import (
"fmt"
)

func main() {
infos := map[string]string{
"a": "A",
}
fmt.Println(fmt.Sprintf("原地址是:%p", &infos))
methodArrayValue(infos)
methodArrayValue1(&infos)
}
func methodArrayValue(infos map[string]string) {
fmt.Println(fmt.Sprintf("值传递的原地址是:%p", &infos))
}
func methodArrayValue1(infos *map[string]string) {
fmt.Println(fmt.Sprintf("地址传递的地址是:%p", infos))
}

打印结果是:
原地址是:0xc042004028
值传递的原地址是:0xc042004038
地址传递的地址是:0xc042004028

结合两个例子打印的值与地址信息,可见map在值传递时原来的值改变了,但是地址信息也改变了说明map在值传递时是重新分配了一个指针指向原来的值。

通过以上的例子可以看出,基本数据类型,结构体,数组在值传递的时候都是重新复制一份传递,而map在值值传递时则是重新分配了一个地址指向原来的值。如果想要提升效率使用地址传递,尤其在多属性的结构体与数组中,因为值传递需要把所有的信息都复制一份来使用;如果只想使用一下其值的信息但并不想改变原有的内容则可以使用值传递。

原文地址
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  go golang