const (
a = iota
b = iota
)
const (
name = "menglu"
c = iota
d = iota
)
func TestExam(t *testing.T) {
fmt.Println(a) // 0
fmt.Println(b) // 1
fmt.Println(c) // 1
fmt.Println(d) // 2
}
// 当使用str1[1:] 使,str2 和 str1 底层共享一个数组,这回导致 str2[1] = "new" 语句影响 str1。
// 而 append 会导致底层数组扩容,生成新的数组,因此追加数据后的 str2 不会影响 str1。
// 但是为什么对 str2 复制后影响的确实 str1 的第三个元素呢?
// 这是因为切片 str2 是从数组的第二个元素开始,
// str2 索引为 1 的元素对应的是 str1 索引为 2 的元素。
func TestExam00(t *testing.T) {
str1 := []string{"a", "b", "c"}
str2 := str1[1:]
str2[1] = "new"
fmt.Println(str1) // [a b new]
str2 = append(str2, "z", "x", "y")
fmt.Println(str2) // [b new z x y]
}
type Student struct {
Name string
Age int
}
func TestExam01(t *testing.T) {
fmt.Println(&Student{Name: "menglu"} == &Student{Name: "menglu"}) // false
fmt.Println(Student{Name: "menglu"} == Student{Name: "menglu"}) // true
}
var mu sync.Mutex
var chain string
func A() {
mu.Lock()
defer mu.Lock()
chain = chain " --> A"
B()
}
func B() {
chain = chain " --> B"
C()
}
func C() {
mu.Lock()
defer mu.Lock()
chain = chain " --> C"
}
// panic
func TestExam02(t *testing.T) {
chain = "main"
A()
fmt.Println(chain)
}
var mu1 sync.RWMutex
var count int
// 去掉一个defer
// 或去掉一重读锁
func A1() {
mu1.RLock()
defer mu1.RUnlock()
B1()
}
func B1() {
time.Sleep(5 * time.Second)
C1()
}
func C1() {
mu1.RLock()
defer mu1.RUnlock()
}
// fatal error: all goroutines are asleep - deadlock!
func TestExam03(t *testing.T) {
go A1()
time.Sleep(2 * time.Second)
mu1.Lock()
defer mu1.Unlock()
count
fmt.Println(count)
}
建议是每调用一次Add(1)方法,再写一个Go程
// panic
func TestExam04(t *testing.T) {
var wg sync.WaitGroup
wg.Add(1)
go func() {
time.Sleep(time.Millisecond)
wg.Done()
wg.Add(1)
}()
wg.Wait()
}
type Once struct {
m sync.Mutex
done uint32
}
func (o *Once) Do(f func()) {
if o.done == 1 {
return
}
o.m.Lock()
defer o.m.Unlock()
if o.done == 0 {
o.done = 1
f()
}
}
func TestExam05(t *testing.T) {
l := Once{}
l.Do(func() {
println("A")
})
for i := 0; i
// panic
func TestExam06(t *testing.T) {
var mu MyMutex
mu.Lock()
var mu2 = mu
mu.count
mu.Unlock()
mu2.Lock() // mu2 其实是已经加锁状态,再加锁会死锁
mu2.count
mu2.Unlock()
fmt.Println(mu.count, mu2.count)
}
// 一直打印: #goroutines: 3
func TestExam08(t *testing.T) {
var ch chan int
go func() {
ch = make(chan int, 1) // 被重新赋值,导致写的ch 都阻塞
ch
func TestExam09(t *testing.T) {
var ch chan int
//ch := make(chan int, 1)
var count int
go func() {
ch
type person struct {
name string
}
func TestExamThree04(t *testing.T) {
var m map[person]int
p := person{"mike"}
// 可以这样处理
//if _, ok := m[p]; !ok {
// println("值不存在")
//} else {
// fmt.Println(m[p])
//}
fmt.Println(m[p]) // 0
}
func hello(num ...int) {
num[0] = 18
}
func TestExamThree05(t *testing.T) {
i := []int{5, 6, 7}
hello(i...)
fmt.Println(i[0]) // 18
}
// 所以 m[key] = &val 取的都是变量 val 的地址,
// 所以最后 map 中的所有元素的值都是变量 val 的地址,
// 因为最后 val 被赋值为3,所有输出都是3
func TestExamThree10(t *testing.T) {
slice := []int{0, 1, 2, 3}
m := make(map[int]*int)
for key, val := range slice {
m[key] = &val
}
//3 -> 3
//0 -> 3
//1 -> 3
//2 -> 3
for k, v := range m {
fmt.Println(k, "->", *v)
}
}
// new(T) 和 make(T,args) 是 Go 语言内建函数,用来分配内存,但适用的类型不同。
//
// new(T) 会为 T 类型的新值分配已置零的内存空间,并返回地址(指针),即类型为 *T 的值。
// 换句话说就是,返回一个指针,该指针指向新分配的、类型为 T 的零值。
// 适用于值类型,如数组、结构体等。
//
// make(T,args) 返回初始化之后的 T 类型的值,
// 这个值并不是 T 类型的零值,也不是指针 *T,是经过初始化之后的 T 的引用。
// make() 只适用于 slice、map 和 channel.
// 相同类型的结构体才能够进行比较,结构体是否相同不但与属性类型有关,还与属性顺序相关
//
// 如果 struct 的所有成员都可以比较,则该 struct 就可以通过 == 或 != 进行比较是否相等,
// 比较时逐个项进行比较,如果每一项都相等,则两个结构体才相等,否则不相等;
// 切片、map、函数等是不能比较的
func TestExamThree13(t *testing.T) {
sn1 := struct {
age int
name string
}{age: 11, name: "qq"}
sn2 := struct {
age int
name string
}{age: 11, name: "qq"}
if sn1 == sn2 {
fmt.Println("sn1 == sn2")
}
// compile failed
sm1 := struct {
age int
m map[string]string
}{age: 11, m: map[string]string{"a": "1"}}
sm2 := struct {
age int
m map[string]string
}{age: 11, m: map[string]string{"a": "1"}}
if sm1 == sm2 {
fmt.Println("sm1 == sm2")
}
}
// 另外一方面,数组的长度也是数组类型的组成部分,
// 所以 a 和 b 是不同的类型,是不能比较的
func run3() {
a := [2]int{5, 6}
b := [3]int{5, 3}
// compile failed
if a == b {
fmt.Println("equal")
} else {
fmt.Println("not equal")
}
}
func TestExamThree19(t *testing.T) {
s := make(map[string]int)
delete(s, "h")
fmt.Println(s["h"])
}
func TestExamThree20(t *testing.T) {
var i interface{}
if i == nil {
fmt.Println("nil")
return
}
fmt.Println("not nil")
}
func TestExamThree24(t *testing.T) {
str := "make([] string, 0)"
// compile failed
str[0] = 'x'
fmt.Println(str)
}
func add(args ...int) int {
sum := 0
for _, arg := range args {
sum = arg
}
return sum
}
// 可变参数就是将任意数目的参数封装成了一个切片
func TestExamThree26(t *testing.T) {
add([]int{1, 3, 7}...)
}
文章中部分知识点参考至:Go 面试每天一篇
参与评论
手机查看
返回顶部