Clarification on using equal sign and map on Go

huangapple go评论78阅读模式
英文:

Clarification on using equal sign and map on Go

问题

为什么在Go语言中map的行为不同?

Go语言中的所有类型都是按值传递的:stringintxxuintxxfloatxxstruct[...]array[]slice,除了map[key]value

并且,将变量作为函数的参数传递等同于使用:=进行赋值。

以下是代码的翻译:

package main

import "fmt"

type test1 map[string]int

func (t test1) DoSomething() { // 不需要使用指针
   t["yay"] = 1
}

type test2 []int

func (t *test2) DoSomething() { // 必须使用指针以便修改生效
	*t = append(*t, 1)
}

type test3 struct {
	a string
	b int
}

func (t *test3) DoSomething() { // 必须使用指针以便修改生效
	t.a = "aaa"
	t.b = 123
}

func main() {
	t1 := test1{}
	u1 := t1
	u1.DoSomething()
	fmt.Println("u1", u1)
	fmt.Println("t1", t1)

	t2 := test2{}
	u2 := t2
	u2.DoSomething()
	fmt.Println("u2", u2)
	fmt.Println("t2", t2)

	t3 := test3{}
	u3 := t3
	u3.DoSomething()
	fmt.Println("u3", u3)
	fmt.Println("t3", t3)
}

package main

import "fmt"

type test1 map[string]int

func DoSomething1(t test1) { // 不需要使用指针
	t["yay"] = 1
}

type test2 []int

func DoSomething2(t *test2) { // 必须使用指针以便修改生效
	*t = append(*t, 1)
}

type test3 struct {
	a string
	b int
}

func DoSomething3(t *test3) { // 必须使用指针以便修改生效
	t.a = "aaa"
	t.b = 123
}

func main() {
	t1 := test1{}
	DoSomething1(t1)
	fmt.Println("t1", t1)

	t2 := test2{}
	DoSomething2(&t2)
	fmt.Println("t2", t2)

	t3 := test3{}
	DoSomething3(&t3)
	fmt.Println("t3", t3)
}

希望对你有帮助!

英文:

Why does map have different behavior on Go?

All types in Go are copied by value: string, intxx, uintxx, floatxx, struct, [...]array, []slice except for map[key]value

package main
import "fmt"
type test1 map[string]int
func (t test1) DoSomething() { // doesn't need to use pointer
t["yay"] = 1
}
type test2 []int
func (t* test2) DoSomething() { // must use pointer so changes would effect
*t = append(*t,1)
}
type test3 struct{
a string
b int
}
func (t* test3) DoSomething() { // must use pointer so changes would effect
t.a = "aaa"
t.b = 123
}
func main() {
t1 := test1{}
u1 := t1
u1.DoSomething()
fmt.Println("u1",u1)
fmt.Println("t1",t1)
t2 := test2{}
u2 := t2
u2.DoSomething()
fmt.Println("u2",u2)
fmt.Println("t2",t2)
t3 := test3{}
u3 := t3
u3.DoSomething()
fmt.Println("u3",u3)
fmt.Println("t3",t3)
}

And passing variable as function's parameter/argument is equal to assignment with :=

package main
import "fmt"
type test1 map[string]int
func DoSomething1(t test1)  { // doesn't need to use pointer
t["yay"] = 1
}
type test2 []int
func DoSomething2(t *test2) { // must use pointer so changes would effect
*t = append(*t,1)
}
type test3 struct{
a string
b int
}
func DoSomething3(t *test3) { // must use pointer so changes would effect
t.a = "aaa"
t.b = 123
}
func main() {
t1 := test1{}
DoSomething1(t1)
fmt.Println("t1",t1)
t2 := test2{}
DoSomething2(&t2)
fmt.Println("t2",t2)
t3 := test3{}
DoSomething3(&t3)
fmt.Println("t3",t3)
}

答案1

得分: 3

值为指针的映射。一些其他类型(切片、字符串、通道、函数)也是通过指针实现的。有趣的是,链接的常见问题解答中提到:

> 早期,映射和通道在语法上是指针,无法声明或使用非指针实例。... 最终,我们决定严格区分指针和值会使语言更难使用。

“Go按值传递”意味着作为常规函数参数传递的变量不会被调用函数修改。这并不改变一些内置类型可以包含指针的事实(就像你自己的结构体一样)。

Python也是类似的:f(x)不会改变传递给它的整数x,但它可以向列表x追加元素,因为Python列表在内部是通过指针实现的。相比之下,C++实际上提供了传引用的方式:如果f被声明为具有引用参数(void f(int& x)),则f(x)可以更改调用者的int x

(我还在回答另一个问题时写了一些关于Go中指针与值的一般信息,如果有帮助的话。)

英文:

Map values are pointers. Some other types (slice, string, channel, function) are, similarly, implemented with pointers. Interestingly, the linked FAQ entry says,

> Early on, maps and channels were syntactically pointers and it was impossible to declare or use a non-pointer instance. ... Eventually we decided that the strict separation of pointers and values made the language harder to use.

"Go passes by value" means variables passed as regular function args won't be modified by the called function. That doesn't change that some built-in types can contain pointers (just like your own structs can).

Python is similar: f(x) won't change an integer x passed to it, but it can append to a list x because Python lists are implemented with a pointer internally. C++, by contrast, has actual pass-by-reference available: f(x) can change the caller's int x if f is declared to have a reference parameter (void f(int& x)).

(I also wrote some general info on pointers vs. values in Go in an answer to another question, if that helps.)

huangapple
  • 本文由 发表于 2014年12月4日 10:07:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/27285067.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定