Golang基础13问

最近看见一篇关于go基础的问题,算是给自己的一个小考验,很多基础的东西当你回过头来看看也许有新的认识,当然这些题也适合出面试题。

Quiz1

package main

import (
	"fmt"
)

func hello() []string {
	return nil
}

func main() {
	h := hello // 这里注意区分 hello()
	if h == nil {
		fmt.Println("nil")
	} else {
		fmt.Println("not nil")
	}

	hs := hello() // 这里注意区分 hello
	if hs == nil {
		fmt.Println("nil")
	} else {
		fmt.Println("not nil")
	}
}

// Answer:
// not nil
// nil

// We assign the function hello() to the variable h in line no. 12 and
// hence h is not nil and the program will print not nil.

Quiz2

package main

import (
	"fmt"
	"strconv"
)

func main() {
	i := 2
	s := "1000"
	if len(s) > 1 { // 注意 变量的作用域
		i, _ := strconv.Atoi(s) // 注意这里的是 := 而不是 =
		i = i + 5
	}
	fmt.Println(i)
}

// Answer
// 2

// The tricky part of the above quiz is line no. 12. i, _ := strconv.Atoi(s) creates a new variable i whose scope is only within the if statement.
// The i which is being printed in line no. 15 is actually the one defined in line no. 9
// and not the one defined in line no. 12. Hence this program will print 2.

Quiz3

package main

import (
	"fmt"
)

func hello(num ...int) {
	num[0] = 18
}

func main() {
	i := []int{5, 6, 7}
	hello(i...) // go 中函数参数都是值传递,但对于slice也把地址传入,所谓的引用类型。
	fmt.Println(i[0])
}

// Answer
// 18

Quiz4

package main

import (
	"fmt"
)

func main() {
	a := [2]int{5, 6}
	b := [2]int{5, 6}
	if a == b {
		fmt.Println("equal")
	} else {
		fmt.Println("not equal")
	}
}

// Answer
// equal

这道题目中对比的是数组,如果换成切片呢?

提示:切片不能用 == 进行比较,可以 进行判断 == nil


Quiz5 ⭐️

package main

import "fmt"

type rect struct {
	len, wid int
}

func (r rect) area() {
	fmt.Println(r.len * r.wid)
	r.len = r.len + 1
}

func (r *rect) add() {
	fmt.Println(r.len + r.wid)
	r.len = r.len + 1
}

func main() {
	r := &rect{len: 5, wid: 6}
	r.area()
	fmt.Println(r.len) // 5 没变

	a := rect{len: 5, wid: 6}
	a.add()
	fmt.Println(a.len) // 6 改变

}

// Answer
// 30
// 5
// 11
// 6

// You might be wondering why the program worked when we didn't use (*r).area() in line no. 21. Since area() has a value receiver,
// Go is intelligent enough to interpret r.area() as (*r).area() and hence this program works :).
// 但只有当方法的接受者为指针形式时才能够在方法内部进行属性操作生效从而改变源数据反之则不能

Quiz6

package main

import (
	"fmt"
)

func main() {
	a := [5]int{1, 2, 3, 4, 5} // 这里是 array
	t := a[3:4:4]              // 这里就成了 slice len == 4-3 cap == 4-3
	fmt.Println(t[0])
	fmt.Println(len(t), cap(t))
}

// Answer
// 4
// 1 1

// a[low : high : max]
// constructs a slice of the same type,
// and with the same length and elements as the simple slice expression a[low : high].
// Additionally, it controls the resulting slice's capacity by setting it to max - low.
// Hence, the slice t in line no.9 has one element 4 and is of capacity 1.

Quiz7 ⭐️

package main

import (
	"fmt"
	"safeuem/common/log"
)

type person struct {
	name string
}

func main() {
	var m map[person]int // 注意这里用 var  和 make 的区别
	p := person{"mike"}
	fmt.Println(m[p])
	v, ok := m[p]
	log.Error(v, ok)
	log.Error(m == nil)
	log.Errorf("%p", m)

}

// Answer
// 0
// 0 false
// true
//  0x0
// var 并没有给变量分配控制内存地址但是对于的值已经初始化为类型零值

Quiz8

package main

import (
	"fmt"
	"safeuem/common/log"
	"strconv"
)

func main() {
	i := 65
	fmt.Println(string(i))

	s := strconv.FormatInt(int64(i), 10) // string与其他类型之间的转换 应该使用 strconv 包
	log.Error(s)
}

// Answer
// A
// 65
// The unicode value of A is 65.
// Hence when i is type casted to string in line no. 9, A is printed.

Quiz9 ⭐️

package main

import (
	"fmt"
)

func main() {
	var i interface{} // 注意 var 声明方式 不会分配内存地址 但会初始化对于类型的零值
	if i == nil {
		fmt.Println("nil")
		return
	}
	fmt.Println("not nil")

}

// Answer
// nil
// An empty interface has both its underlying value and concrete type as nil. Hence i is nil

这道题,请自行查看interface 与 nil 的知识点


Quiz10 ⭐️

package main

import (
	"fmt"
)

func hello(i int) {
	fmt.Println(i)
}
func main() {
	i := 5
	defer hello(i) // defer 函数的参数 是在声明时进行读入值,而不是在实际调用时才读入
	i = i + 10
}

// Answer
// 5
// The arguments of a deferred function are evaluated
// when the defer statement is executed and not when the actual function call is done.
// Hence when the defer statement is encountered in line no. 12, the value of i is 5.
// So this program will print 5.

这道题关于defer其中一个知识点,关于defer的知识点还有其他,自行查看吧。


Quiz11

package main

import (
	"fmt"
)

func main() {
	fmt.Printf("%%") // 输出 % 本体
}

// Answer
// %
// The format specifier %% prints a literal % sign. Hence the program prints %.

这里直接补充下:

动 词 功 能
%v 按值的本来值输出
%+v 在 %v 基础上,对结构体字段名和值进行展开
%#v 输出 Go 语言语法格式的值
%T 输出 Go 语言语法格式的类型和值
%% 输出 % 本体
%b 整型以二进制方式显示
%o 整型以八进制方式显示
%d 整型以十进制方式显示
%+d 整型以十进制方式显示并显示数字的符号
%x 整型以十六进制方式显示
%X 整型以十六进制、字母大写方式显示
%U Unicode 字符
%f 浮点数
%p 指针,十六进制方式显示

Quiz12

package main

import (
	"fmt"
)

func main() {
	s := make(map[string]int)
	delete(s, "h")
	fmt.Println(s["h"])
}

// Answer
// 0
// The delete function in line no. 9 doesn't return anything and will do nothing if the specified key doesn't exist.
// Since the key h doesn't exist,
// the delete function will not do anything. In line no. 10, we are trying to print s["h"].
// Since the map s doesn't have the key h, it will return the default value of int. Hence 0 will be printed.

Quiz13

package main

import (
	"fmt"
)

func main() {
	i := -5
	j := +5
	fmt.Printf("%+d %+d", i, j) // +d 表示始终打出数字的符号
}

// Answer
// -5 +5
// The + flag in the format specifier %+d is used to always print a sign for numeric values.
// Hence this program outputs -5 +5.