关于 Golang 中 make 函数的疑惑

2022-04-11 17:42:07 +08:00
 hzjseasea

Go 里面 make 返回的是 和传入参数的同类型的实例(Type) 还是传入参数同类型的指针(*Type)

https://go.dev/doc/effective_go#allocation_make , 官方的文档里面有写道

The built-in function make(T, args) serves a purpose different from new(T). It creates slices, maps, and channels only, and it returns an initialized (not zeroed) value of type T (not *T)

源码里面也有写到 /usr/local/opt/go/libexec/src/builtin/builtin.go

// The make built-in function allocates and initializes an object of type
// slice, map, or chan (only). Like new, the first argument is a type, not a
// value. Unlike new, make's return type is the same as the type of its
// argument, not a pointer to it. The specification of the result depends on
// the type:
//	Slice: The size specifies the length. The capacity of the slice is
//	equal to its length. A second integer argument may be provided to
//	specify a different capacity; it must be no smaller than the
//	length. For example, make([]int, 0, 10) allocates an underlying array
//	of size 10 and returns a slice of length 0 and capacity 10 that is
//	backed by this underlying array.
//	Map: An empty map is allocated with enough space to hold the
//	specified number of elements. The size may be omitted, in which case
//	a small starting size is allocated.
//	Channel: The channel's buffer is initialized with the specified
//	buffer capacity. If zero, or the size is omitted, the channel is
//	unbuffered.
func make(t Type, size ...IntegerType) Type

那说明返回的内容就是一个和传入参数同类型的实例

然后在 /usr/local/opt/go/libexec/src/runtime/map.go runtime 包里面的 makemap 函数返回的是一个*T 的内容

// makemap implements Go map creation for make(map[k]v, hint).
// If the compiler has determined that the map or the first bucket
// can be created on the stack, h and/or bucket may be non-nil.
// If h != nil, the map can be created directly in h.
// If h.buckets != nil, bucket pointed to can be used as the first bucket.
func makemap(t *maptype, hint int, h *hmap) *hmap {
	mem, overflow := math.MulUintptr(uintptr(hint), t.bucket.size)
	if overflow || mem > maxAlloc {
		hint = 0
	}

	// initialize Hmap
	if h == nil {
		h = new(hmap)
	}
	h.hash0 = fastrand()

	// Find the size parameter B which will hold the requested # of elements.
	// For hint < 0 overLoadFactor returns false since hint < bucketCnt.
	B := uint8(0)
	for overLoadFactor(hint, B) {
		B++
	}
	h.B = B

	// allocate initial hash table
	// if B == 0, the buckets field is allocated lazily later (in mapassign)
	// If hint is large zeroing this memory could take a while.
	if h.B != 0 {
		var nextOverflow *bmap
		h.buckets, nextOverflow = makeBucketArray(t, h.B, nil)
		if nextOverflow != nil {
			h.extra = new(mapextra)
			h.extra.nextOverflow = nextOverflow
		}
	}

	return h
}

有无大佬帮忙解释一下

1620 次点击
所在节点    Go 编程语言
8 条回复
pigmen
2022-04-11 17:58:38 +08:00
map := *hmap

可以这么理解
josephxrays
2022-04-11 19:31:36 +08:00
labulaka521
2022-04-11 22:35:21 +08:00
我觉得 make 返回的不是指针,但返回的类型底层实现是一个指针
hzjseasea
2022-04-12 10:01:01 +08:00
@labulaka521 源码里面返回的是一个指针, 然后编译期的源码在这个下面 /usr/local/opt/go/libexec/src/cmd/compile/internal/gc/builtin/runtime.go
```
func makemap(mapType *byte, hint int, mapbuf *any) (hmap map[any]any)
```
返回的不是一个指针
tairan2006
2022-04-12 10:18:51 +08:00
labulaka521
2022-04-12 12:19:11 +08:00
@hzjseasea slice 和 map 还不太一致 我看了下确实是指向一个 hmap 的指针
hzjseasea
2022-04-12 14:34:22 +08:00
fy1206
2022-06-01 14:01:40 +08:00
楼主 给个联系方式 交流一下

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/846327

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX