1.下面代码输出什么,为什么
//make([]T, length, capacity) s1 := []int{1, 2, 3} fmt.Println(s1, "哈哈") //[1 2 3] s2 := s1 fmt.Println(s1, "哈哈") //[1 2 3] for i := 0; i < 3; i++ { s2[i] = s2[i] + 1 } fmt.Println(s1) //[2 3 4] fmt.Println(s2) //[2 3 4]
[1 2 3] 哈哈
[1 2 3] 哈哈
[2 3 4]
[2 3 4]
注:引用就是同一份,相当于起了一个别名,就是多起了一个名字而已。
在Go语言中的引用类型有:映射(map),数组切片(slice),通道(channel),方法与函数。
整型,字符串,布尔,数组在当作参数传递时,是传递副本的内存地址,也就是值传递。
2.下面代码输出什么,为什么
func rmLast(a []int) { fmt.Println("a", a) a = a[:len(a)-1] for i := 0; i < 13; i++ { a = append(a, 8) } fmt.Println("rm后a", a) // fmt.Println(len(a)) } func updateLast(a []int) { fmt.Println("a", a) for i := 0; i < len(a); i++ { a[i] = a[i] + 1 } fmt.Println("修改后a", a) // fmt.Println(len(a)) } func main() { xyz := []int{1, 2, 3, 4, 5, 6, 7, 8, 9} fmt.Println("xyz", xyz) rmLast(xyz) fmt.Println("rm后xyz", xyz) updateLast(xyz) fmt.Println("修改后xyz", xyz) //[1 2 3 4 5 6 7 8 9] }
xyz [1 2 3 4 5 6 7 8 9]
a [1 2 3 4 5 6 7 8 9]
rm后a [1 2 3 4 5 6 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8]
rm后xyz [1 2 3 4 5 6 7 8 8]
a [1 2 3 4 5 6 7 8 8]
修改后a [2 3 4 5 6 7 8 9 9]
修改后xyz [2 3 4 5 6 7 8 9 9]
注:函数内改切片的值,外部是可见的,改切片的长度外部是不可见的
3.下面代码输出什么,为什么
//n1是n2的底层数组
n1 := [3]int{1, 2, 3}
n2 := n1[0:3]
fmt.Println("下面是n1地址 ")
for i := 0; i < len(n1); i++ {
fmt.Printf("%p\n", &n1[i])
}
fmt.Println(n1)
fmt.Println("下面是n2地址 ")
for i := 0; i < len(n2); i++ {
fmt.Printf("%p\n", &n2[i])
}
fmt.Println(n2)
n2 = append(n2, 1)
fmt.Println("下面是n1地址 ")
for i := 0; i < len(n1); i++ {
fmt.Printf("%p\n", &n1[i])
}
fmt.Println(n1)
fmt.Println("下面是n2地址 ")
for i := 0; i < len(n2); i++ {
fmt.Printf("%p\n", &n2[i])
}
fmt.Println(n2)
下面是n1地址
0xc000064140
0xc000064148
0xc000064150
[1 2 3]
下面是n2地址
0xc000064140
0xc000064148
0xc000064150
[1 2 3]
下面是n1地址
0xc000064140
0xc000064148
0xc000064150
[1 2 3]
下面是n2地址
0xc000090030
0xc000090038
0xc000090040
0xc000090048
[1 2 3 1]
4.下面代码输出什么,为什么
func defer_call(y int) {
for i := 0; i < 5; i++ {
defer fmt.Println("输出y+i", y+i)
fmt.Println("哈哈")
defer fmt.Println("输出i ", i)
}
}
func main() {
defer_call(5)
}
哈哈
哈哈
哈哈
哈哈
哈哈
输出i 4
输出y+1 9
输出i 3
输出y+1 8
输出i 2
输出y+1 7
输出i 1
输出y+1 6
输出i 0
输出y+1 5
注:先执行"哈哈",
退出defer_call这个函数时,反序执行以下函数
fmt.Println("输出y+i",5)
fmt.Println("i",0)
fmt.Println("输出y+i",6)
fmt.Println(....)
fmt.Println("输出y+i",9)
fmt.Println("i",4)
5.下面代码输出什么
func main() {
for i := 0; i < 5; i++ {
fmt.Println(i, "haha")
//匿名函数:匿名函数可以在声明后调用
go func() {
time.Sleep(3 * time.Second)
fmt.Println(i, "嗯嗯")
}()
}
time.Sleep(10 * time.Second)
}
0 haha
1 haha
2 haha
3 haha
4 haha
5 嗯嗯
5 嗯嗯
5 嗯嗯
5 嗯嗯
5 嗯嗯
6.下面代码输出什么
func main() {
strs := []string{"one", "two", "three"}
for _, s := range strs {
//1.主线程都快结束了(主线程跑到three了),并发出来的线程才刚开始
//2.这里匿名函数不传参的话,是共享的s的地址,所以打印出来的都是three
go func() {
time.Sleep(1 * time.Second)
fmt.Printf("%s ", s)
}()
}
time.Sleep(3 * time.Second)
}
three three three
7.下面代码输出什么
func main() {
strs := []string{"one", "two", "three"}
for _, s := range strs {
go func(s string) {
time.Sleep(1 * time.Second)
fmt.Printf("%s ", s)
}(s)
}
time.Sleep(3 * time.Second)
}
three one two
one two three
one three two
注:并发出来三个线程,哪个先结束不一定,所以输出不固定
8.下面代码输出什么
func main() {
x := []string{"ha", "b", "c"}
for v := range x {
fmt.Print(v)
}
}
012
9.下面代码输出什么
type Slice []int
func NewSlice() Slice {
return make(Slice, 0)
}
func (s *Slice) Add(elem int) *Slice {
*s = append(*s, elem)
fmt.Print(elem)
return s
}
func main() {
s := NewSlice()
defer s.Add(1).Add(2)
s.Add(3)
}
132
注:一个defer只能延迟调用一个函数,defer s.Add(1).Add(2),先执行参数部分,然后再延迟调用Add(2)
10.下面代码输出什么
package main
import (
"fmt"
)
func main() {
defer_call()
}
func defer_call() {
defer func() { fmt.Println("打印前") }()
defer func() { fmt.Println("打印中") }()
defer func() { fmt.Println("打印后") }()
panic("触发异常")
}
考点:defer执行顺序
解答:
defer 是后进先出。
panic 需要等defer 结束后才会向上传递。 出现panic恐慌时候,会先按照defer的后入先出的顺序执行,最后才会执行panic。
打印后
打印中
打印前
panic: 触发异常
11.下面代码输出什么
package main
import (
"fmt"
)
// 遍历切片的每个元素, 通过给定函数进行元素访问
func visit(list []int, f func(int)) {
for _, v := range list {
f(v)
}
}
func main() {
// 使用匿名函数打印切片内容
visit([]int{1, 2, 3, 4}, func(v int) {
fmt.Println(v)
})
}
12.下面代码输出什么
package main
import (
"fmt"
"runtime"
"sync"
)
func main() {
//GOMAXPROCS设置可同时执行的最大CPU数,并返回先前的设置。
// 若 n < 1,它就不会更改当前设置。本地机器的逻辑CPU数可通过 NumCPU 查询。
//本函数在调度程序优化后会去掉。
runtime.GOMAXPROCS(1)
wg := sync.WaitGroup{}
wg.Add(20)
for i := 0; i < 10; i++ { //主线程
go func() { //并发出来的线程
fmt.Println("A: ", i)
wg.Done()
}()
}
for i := 0; i < 10; i++ {
go func(i int) {
fmt.Println("B: ", i)
wg.Done()
}(i)
}
wg.Wait()
}
考点:go执行的随机性和闭包
解答:
谁也不知道执行后打印的顺序是什么样的,所以只能说是随机数字。 但是A:均为输出10,B:从0~9输出(顺序不定)。 第一个go func中i是外部for的一个变量,地址不变化。遍历完成后,最终i=10。 故go func执行时,i的值始终是10。
第二个go func中i是函数参数,与外部for中的i完全是两个变量。 尾部(i)将发生值拷贝,go func内部指向值拷贝地址。
13.下面代码输出什么
package main
import (
"fmt"
"runtime"
"sync"
)
func main() {
//GOMAXPROCS设置可同时执行的最大CPU数,并返回先前的设置。
// 若 n < 1,它就不会更改当前设置。本地机器的逻辑CPU数可通过 NumCPU 查询。
//本函数在调度程序优化后会去掉。
runtime.GOMAXPROCS(2)
wg := sync.WaitGroup{}
wg.Add(3)
for i := 0; i < 10; i++ { //主线程
go func() { //并发出来的线程
fmt.Println("A: ", i)
wg.Done()
}()
}
wg.Wait()
wg.Add(7)
wgg := sync.WaitGroup{}
wgg.Add(5)
for i := 0; i < 10; i++ {
go func(i int) {
fmt.Println("B: ", i)
wgg.Done()
}(i)
}
wgg.Wait()
}
14.下面代码会触发异常吗?请详细说明
package main
import (
"fmt"
"runtime"
)
func main() {
runtime.GOMAXPROCS(1)
int_chan := make(chan int, 1)
string_chan := make(chan string, 1)
int_chan <-1
string_chan <-"hello"
select {
case value := <-int_chan:
fmt.Println(value)
case value := <-string_chan:
panic(value)
}
}
考点:select随机性
解答:
select会随机选择一个可用通用做收发操作。 所以代码是有肯触发异常,也有可能不会。 单个chan如果无缓冲时,将会阻塞。但结合 select可以在多个chan间等待执行。有三点原则:
select 中只要有一个case能return,则立刻执行。
当如果同一时间有多个case均能return则伪随机方式抽取任意一个执行。
如果没有一个case能return则可以执行”default”块。
15.下面代码有什么问题,如何修改
package main
import (
"fmt"
"sync"
)
type UserAges struct {
ages map[string]int
sync.Mutex
}
func (ua *UserAges) Add(name string, age int) {
ua.Lock()
defer ua.Unlock()
ua.ages[name] = age
}
func (ua *UserAges) Get(name string) int {
if age, ok := ua.ages[name]; ok {
return age
}
return -1
}
func main() {
var userAges UserAges
userAges.Add("lisa", 24)
userAges.Get("lisa")
fmt.Println(userAges.ages)
}
panic: assignment to entry in nil map
goroutine 1 [running]:
main.(*UserAges).Add(0xc0000521c0, 0x4c492f, 0x4, 0x18)
C:/Users/zyq/go/src/yj/ra.go:17 +0x98
main.main()
C:/Users/zyq/go/src/yj/ra.go:28 +0x69
exit status 2
修改后:
func (ua *UserAges) Add(name string, age int) {
ua.ages = make(map[string]int)
ua.Lock()
defer ua.Unlock()
ua.ages[name] = age
}
输出结果:
map[lisa:24]
16.下面代码输出什么,为什么
package main
import (
"fmt"
"sync"
)
type threadSafeSet struct {
sync.RWMutex
s []interface{}
}
func (set *threadSafeSet) Iter() <-chan interface{} {
// ch := make(chan interface{}) // 解除注释看看!
ch := make(chan interface{}, len(set.s))
go func() {
set.RLock()
for _, elem := range set.s {
ch <- elem
fmt.Println("Iter:", elem)
}
close(ch)
set.RUnlock()
}()
return ch
}
func main() {
th := threadSafeSet{
s: []interface{}{"1", "2"},
}
v := <-th.Iter()
fmt.Println(v)
}
Iter: 1
Iter: 2
解答:ch := make(chan interface{}, len(set.s)) 每次都会分配一个新的channel,v := <-th.Iter()只传了一个值,所以v是数组s的第一个value
17.以下代码输出什么?为什么?
package main
import (
"fmt"
)
type People interface {
Show()
}
type Student struct{}
func (stu *Student) Show() {
}
func live() People {
var stu *Student
return stu
}
func main() {
if live() == nil {
fmt.Println("AAAAAAA")
} else {
fmt.Println("BBBBBBB")
}
}
输出:
BBBBBBB
18.以下代码输出什么?为什么?
package main
func main() {
i := GetValue()
switch i.(type) {
case int:
println("int")
case string:
println("string")
case interface{}:
println("interface")
default:
println("unknown")
}
}
func GetValue() int {
return 1
}
解析
考点:type
编译失败,因为type只能使用在interface
修改后:
package main func main() { i := GetValue() switch i.(type) { case int: println("int") case string: println("string") case interface{}: println("interface") default: println("unknown") } } func GetValue() interface{} { return 1 }
package main
func main() {
i := GetValue()
switch i.(type) {
case int:
println("int")
case string:
println("string")
case interface{}:
println("interface")
default:
println("unknown")
}
}
func GetValue() interface{} {
return 1
}
19.以下代码输出什么?为什么?
package main
import "fmt"
func main() {
s1 := []int{1, 2, 3}
s2 := []int{4, 5}
s1 = append(s1, s2...)
fmt.Println(s1)
fmt.Println(s2)
var a = []int{1, 2, 3}
a = append([]int{0}, a...)
fmt.Println(a)
a = append([]int{-3, -2, -1}, a...)
fmt.Println(a)
}
[1 2 3 4 5]
[4 5]
[0 1 2 3]
[-3 -2 -1 0 1 2 3]
考点:
1.追加一个切片, 切片需要解包s1 = append(s1, s2…)
2.除了在切片的尾部追加,我们还可以在切片的开头添加元素
20.以下代码输出什么?为什么?
package main
import "fmt"
func GetValue(m map[int]string, id int) (string, bool) {
if _, exist := m[id]; exist {
return "存在数据", true
}
return "", false
}
func main() {
intmap := map[int]string{
1: "a",
2: "bb",
3: "ccc",
}
v, err := GetValue(intmap, 3)
fmt.Println(v, err)
}
存在数据 true
考点:map的key是否存在
21.以下代码输出什么?为什么?
package main
func DeferFunc1(i int) (t int) {
t = i
defer func() {
t += 3
}()
return t
}
func DeferFunc2(i int) int {
t := i
defer func() {
t += 3
}()
return t
}
func DeferFunc3(i int) (t int) {
defer func() {
t += i
}()
return 2
}
func main() {
println(DeferFunc1(1))
println(DeferFunc2(1))
println(DeferFunc3(1))
}
更多相关技术资讯内容欢迎前往六星社区了解。
如果你想用Python开辟副业赚钱,但不熟悉爬虫与反爬虫技术,没有接单途径,也缺乏兼职经验
关注下方微信公众号:Python编程学习圈,获取价值999元全套Python入门到进阶的学习资料以及教程,还有Python技术交流群一起交流学习哦。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!