# Go语言--空结构体struct{}解析

19 篇文章 3 订阅

### 简介

1. 做控制而非数据信息： chan struct{}
2. 实现set: map[string]struct{}

### 解析

1. type Q struct{}
2. var q struct{}

var s string
var c complex128
fmt.Println(unsafe.Sizeof(s)) // prints 8
fmt.Println(unsafe.Sizeof(c)) // prints 16

var a [3]uint32
fmt.Println(unsafe.Sizeof(a)) // prints 12

type S struct {
a uint16
b uint32
}
var s S
fmt.Println(unsafe.Sizeof(s)) // prints 8, not 6

var s struct{}
fmt.Println(unsafe.Sizeof(s)) // prints 0

type S struct {
A struct{}
B struct{}
}
var s S
fmt.Println(unsafe.Sizeof(s)) // prints 0

var x [1000000000]struct{}
fmt.Println(unsafe.Sizeof(x)) // prints 0

var x = make([]struct{}, 1000000000)
fmt.Println(unsafe.Sizeof(x)) // prints 12 in the playground

ar x = make([]struct{}, 100)
var y = x[:50]
fmt.Println(len(y), cap(y)) // prints 50 100

var a struct{}
var b = &a

var a, b struct{}
fmt.Println(&a == &b) // false

a := make([]struct{}, 10)
b := make([]struct{}, 20)
fmt.Println(&a == &b) // false, a and b are different slices
fmt.Println(&a[0] == &b[0]) // true, their backing arrays are the same

a := struct{}{} // not the zero value, a real new struct{} instance
b := struct{}{}
fmt.Println(a == b) // true

type S struct{}
func (s *S) addr() { fmt.Printf("%p\n", s) }
func main() {
var a, b S
}

### chan struct{}

Go语言中，有一种特殊的struct{}类型的channel，它不能被写入任何数据，只有通过close()函数进行关闭操作，才能进行输出操作。struct{}类型的channel不占用任何内存！！！

var sig = make(chan struct{})

package main

import "fmt"
import "time"

var strChan = make(chan string,3)

func main(){
syncChan1 := make(chan struct{},1)  //接收同步变量
syncChan2 := make(chan struct{},2) //主线程启动了两个goruntime线程，
//等这两个goruntime线程结束后主线程才能结束

//用于演示接受操作
go func(){
<- syncChan1  //表示可以开始接收数据了，否则等待
time.Sleep(time.Second)
for{
if elem,ok := <-strChan;ok{
}else{
break
}
}
syncChan2 <- struct{}{}
}()

//用于演示发送操作
go func(){
for i,elem := range []string{"a","b","c","d"}{
fmt.Println("[sender] Sent:",elem)
strChan <- elem
if (i+1)%3==0 {
syncChan1 <- struct{}{}
fmt.Println("[sender] Sent a sync signal. wait 1 secnd...")
time.Sleep(time.Second)
}
}
fmt.Println("[sender] wait 2 seconds...")
time.Sleep(time.Second)
close(strChan)
syncChan2 <- struct{}{}
}()

//主线程等待发送线程和接收线程结束后再结束
fmt.Println("[main] waiting...")
<- syncChan2
<- syncChan2
fmt.Println("[main] stoped")
}

[main] waiting...
[sender] Sent: a
[sender] Sent: b
[sender] Sent: c
[sender] Sent a sync signal. wait 1 secnd...
[sender] Sent: d
[sender] wait 2 seconds...
[main] stoped
• struch{}代表不包含任何字段的结构体类型，也可称为空结构体类型。在go语言中，空结构体类型是不占用系统内存的，并且所有该类型的变量都拥有相同的内存地址。建议用于传递信号的通道都以struct{}作为元素类型，除非需要传递更多的信息
• 发送方向通道发送的值会被复制，接收方接收到的总是该值得副本，而不是该值本身。经由通道传递的值最少会被复制一次，最多会被复制两次。例如，当向一个已空的通道发送值，且已有至少一个接收方因此等待时，该通道会绕过本身的缓冲队列，直接把这个值复制给最早等待的那个接收方，这种情况传递的值只复制一次；当从一个已满的通道接收值，且已有至少一个发送方因此等待时，该通道会把缓冲队列中最早进入的那个值复制给接收方，再把最早等待的发送方要发送的数据复制到那个值得原先位置上（通道的缓冲队列属于环形队列，这样做是没有问题的），这种情况传递的值复制两次。
• 通道传递是复制传递的值。因此如果传递的是值类型，接收方对该值得修改不会影响发送方持有的值；如果传递的是引用类型，则发送方或者接收方对该对象的修改会影响双方所持有的对象

End

• 12
点赞
• 23
收藏
觉得还不错? 一键收藏
• 4
评论
02-10 519
06-23 1万+
02-21 330
10-14 4万+
08-13
07-25 2943
01-22 1019
05-24 690
05-04 264
08-19 174
02-15 972
05-31 270

### “相关推荐”对你有帮助么？

• 非常没帮助
• 没帮助
• 一般
• 有帮助
• 非常有帮助

1.余额是钱包充值的虚拟货币，按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载，可以购买VIP、付费专栏及课程。