①★GO语言面试之数据格式舒适版♥√

Posted 行走的皮卡丘

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了①★GO语言面试之数据格式舒适版♥√相关的知识,希望对你有一定的参考价值。

①★GO语言面试之数据格式👈

1、🐹数组和切片

1.1 ☀️有如下代码,请说明两个切片的不同

msg := []int{1,2,3,4,5,6,7,8,9};
sli1 := msg[2:3:4]
sli2 := msg[2:3] 

答:

考点: 切⽚容量
⾥⾯的数据⼀样,但是两个切⽚的容量不⼀样
容量 = max - low

1.2 ❄️写出下面程序运行的结果

func main(){
	abc := make([]int,2)
	abc = append(abc,1,2,3)
	fmt.Println(abc) 
}

答:

考点 切⽚追加
结果:[0 0 0 0 0 0 0 0 0 0 1 2 3]

1.3 🐱下面代码输出什么?

package main
import "fmt"

func main(){
	arr:=[]int{1,2,3,4,5,6,7,8}
	s1:=arr[2:6]
	s2:=s1[3:6] 
	fmt.Println("s1==",s1)
	fmt.Println("s2==",s2) 
}

答:

考点:切⽚截取
结果:
s1== [3 4 5 6]
s2== [6 7 8]

1.4 🐹是否可以编译通过?如果通过,输出什么?

package main
import "fmt"

func main() {
	s1 := []int{1, 2, 3}
	s2 := []int{4, 5}
	s1 = append(s1, s2)
	fmt.Println(s1) 
}

答:

考点:append追加不定参
append切⽚时候别漏了’…’

结果:编译失败。

1.5 🐮解释Slice和Array的区别

答:

考点:数组和切⽚
结果:
array是固定⻓度的数组,使⽤前必须确定数组⻓度。

slice是⼀个引⽤类型,是⼀个动态的指向数组切⽚的指针。
slice是⼀个不定⻓的,总是指向底层的数组array的数据结构。

数组是值类型,把⼀个数组赋予给另⼀个数组时是发⽣值拷⻉,⽽切⽚是指针类型,拷⻉的是指针。
所以在golang的⽅法中即使是值传递切⽚,其实也是传递的指针。

数组⼤⼩是固定的,切⽚⼤⼩不是。在运⾏时可以动态地增加或减少切⽚的⼤⼩,但数组不可以。切
⽚类似于链表,可以向切⽚push,pop数据,实现FIFO,LIFO。使⽤了内置的添加、复制功能对切
⽚操作

1.6 🎍slice的底层实现

答:

考点:slice的底层实现
结果:
slice底层存储了三个内容:地址、⻓度、容量。
地址是指数据存储的位置。
⻓度表示有效数据的个数。
容量表示本次(不更换地址)可以扩容的最⼤值。
⻓度和容量随着append的添加⽽改变,地址可能改变。

2、🐑map

2.1 🎒写出⼀下程序运⾏的结果

package main
import ( 
	"fmt"
)

func main(){
	dict:=map[string]int{"王五":60,"张三":43}
	modify(dict)
	fmt.Println(dict["张三"])
}

func modify(dict map[string]int){
	dict["张三"]=10
}

答:

考点:map作为函数参数,引⽤传递。
map作为函数参数是引⽤传递,形参可以修改实参的值。

结果:10

2.2 ☁️编译并运行如下代码会发生什么?

package main
import "fmt"

type Test struct {
	Name string
}

var list map[string]Test

func main() {
	list = make(map[string]Test)
	name := Test{"xiaoming"}
	list["name"] = name
	list["name"].Name = "Hello"
	fmt.Println(list["name"])
}

答:

考点:map
结果:编译失败。
编程报错 cannot assign to struct field list[“name”].Name in map 。 因为
list[“name”]不是⼀个普通的指针值,map的value本身是不可寻址的,因为map中的值会在内存
中移动,并且旧的指针地址在map改变时会变得⽆效。 定义的是var list map[string]Test,注意
哦Test不是指针,⽽且map我们都知道是可以⾃动扩容的,那么原来的存储name的Test可能在地
址A,但是如果map扩容了地址A就不是原来的Test了,所以go就不允许写数据。改为var list
map[string]*Test。

2.3 💝Map的键类型不能是哪些类型?

答:

考点:map的键
结果:字典的键类型不能是以下类型:函数类型,字典类型,切⽚类型
键类型的值之间必须⽀持判等操作,函数类型,字典类型,切⽚类型不⽀持判等操作
字典是引⽤类型,只声明⽽不初始化,值是nil。除了添加键-元素对,在值为nil的字典上操作都不
会引起错误。

3、🎑数据定义

3.1 🎅是否可以编译通过?如果通过,输出什么?

const (
	x = iota
	y
	z = "zz"
	k
	p = iota
)

func main() {
	fmt.Println(x,y,z,k,p) 
}

答:

考点:常量定义和iota枚举赋值
结果:0 1 zz zz 4
iota 换⾏值+1

3.2 🔔编译执⾏下⾯代码会出现什么?

package main

var(
	size :=1024
	max_size = size*2 
 )
 
func main() {
	println(size,max_size) 
 }

答:

考点:全局变量定义
结果:编译失败。
常量不允许使⽤⾃动推导类型。

3.3 📣下⾯函数有什么问题?

package main

const cl = 100
var bl = 123

func main() {
	println(&bl,bl)
	println(&cl,cl) 
}

答:

考点:常量
结果:编译失败。
常量不同于变量的在运⾏期分配内存,常量通常会被编译器在预处理阶段直接展开,作为指令数
据使⽤,报错:cannot take the address。

3.4 💣编译执行下面代码会出现什么?

package main
import "fmt"

func main() {
	type MyInt1 int
	type MyInt2 = int
	var i int = 9
	var i1 MyInt1 = i
	var i2 MyInt2 = i
	fmt.Println(i1,i2) 
}

答:

考点:type起别名
基于⼀个类型创建⼀个新类型,称之为defintion;基于⼀个类型创建⼀个别名,称之为alias。
MyInt1为称之为defintion,虽然底层类型为int类型,但是不能直接赋值,需要强转; MyInt2称
之为alias,可以直接赋值。

结果:编译失败。报错:annot use i (type int) as type MyInt1 in assignment。

3.5 🏠string和[ ]byte的区别

答:

考点:string和[ ]byte的区别
结果:
共同点可以互相转化、都可以通过下标索引
不同点:

  • 1、[ ]byte可以通过下标修改值,string不可以
  • 2、string可以⽐较,[ ]byte不可以⽐较,所以[ ]byte不能作为map的key值
  • 3、[ ]byte在传输性能⽅⾯要⽐string
  • 4、string的值不可以为nil,所以如果需要nil的特性,就得⽤[]byte

4、😄指针

4.1🍆 是否可以编译通过?如果通过,输出什么?

func main() {
	list := new([]int)
	list = append(list, 1)
	fmt.Println(list) 
}

答:

考点:new和make
结果:编译失败。
切⽚指针的解引⽤。
可以使⽤list:=make([]int,0) list类型为切⽚
或使⽤*list = append(*list, 1) list类型为指针

4.2 💜make和new的区别

答:

考点:new和make
结果:⼆者都是内存的分配(堆上),但是make只⽤于slice、map以及channel的初始化(⾮零值);⽽
new⽤于类型的内存分配,并且内存置为零。所以在我们编写程序的时候,就可以根据⾃⼰的需要很
好的选择了。
make返回的还是这三个引⽤类型本身;⽽new返回的是指向类型的指针。

5、💕interface

5.1 👍以下代码输出什么?

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 }

答:

考点:interface{}类型和函数类型
结果:编译失败。
因为type只能使⽤在interface

5.2 🐷是否可以编译通过?如果通过,输出什么?

func Foo(x interface{}) {
	if x == nil {
		fmt.Println("empty interface")
		return
 	}
 	fmt.Println("non-empty interface") 
}

func main() {
	var x *int = nil
	Foo(x) 
}

答:

考点:interface内部结构
结果:non-empty interface

5.3 🐌ABCD中哪一些存在错误?

type S struct {
}
func f(x interface{}) {
}
func g(x *interface{}) {
}
func main() {
	s := S{}
	p := &s
	
	f(s) //A
	g(s) //B
	f(p) //C
	g(p) //D
}

答:

考点:interface
结果:B和D错误。
看到这道题需要第⼀时间想到的是Golang是强类型语⾔,interface是所有golang类型的⽗类, 函
数中 func f(x interface{}) 的 interface{} 可以⽀持传⼊golang的任何类型,包括指针,但
是函数 func g(x *interface{}) 只能接受 *interface{} .

6、🍄函数和闭包

6.1 🌝下面函数有什么问题?

func funcMui(x,y int)(sum int,error){
	return x+y,nil
}

答:

考点:函数返回值命名
结果:编译出错。
在函数有多个返回值时,只要有⼀个返回值有指定命名,其他的也必须有命名。 如果返回值有有
多个返回值必须加上括号; 如果只有⼀个返回值并且有命名也需要加上括号; 此处函数第⼀个返
回值有sum名称,第⼆个未命名,所以错误。

6.2 🌔是否可以编译通过?如果通过,输出什么?

func GetValue(m map[int]string, id int) (string, bool) {
	if _, exist := m[id]; exist {
		return "存在数据", true
	}
	return nil, false
}

func main() {
	intmap:=map[int]string{
	1:"a",
	2:"bb",
	3:"ccc",
	}
	v,err:=GetValue(intmap,3)
	fmt.Println(v,err) 
}

答:

考点:函数返回值类型
结果:编译失败。
nil 可以⽤作 interface、function、pointer、map、slice 和 channel 的“空值”。但是如果不特别
指定的话,Go 语⾔不能识别类型,所以会报错。

6.3 🔎编译执⾏下⾯代码会出现什么?

package main

func main() {
	for i:=0;i<10 ;i++ {
		loop:
		println(i)
	}
	goto loop
	}

答:

考点:goto跳转语句
结果:编译失败。
goto不能跳转到其他函数或者内层代码,报错:goto loop jumps into block starting at。

6.4 🏀编译执行下面代码会出现什么?

package main

func test() []func() {
	var funs []func()
	for i:=0;i<2 ;i++ {
		funs = append(funs, func() {
		println(&i,i)
	})
 }
 return funs
}
func main(){
	funs:=test()
	for _,f:=range funs{
		f()
	}
}

答:

考点:闭包延迟求值 for循环复⽤局部变量i,每⼀次放⼊匿名函数的应⽤都是同⼀个变量。
结果:
0xc042046000 2
0xc042046000 2

如果想不⼀样:

func test() []func() {
	var funs []func()
	for i:=0;i<2 ;i++ {
		x:=i
		funs = append(funs, func() {
			println(&x,x)
		})
	}
	return funs
}

结果:
0xc000096000 0
0xc000096008 1

6.5🍪 编译执行下面代码会出现什么?

package main

func test(x int) (func(),func()) {
	return func() {
	println(x)
	x+=10
	}, func() {
	println(x)
	}
}
func main() {
	a,b:=test(100)
	a()
	b()
}

答:

考点:闭包引⽤相同变量
结果:
100
110

6.6 🍭输出什么?

package main
import (
	 "fmt"
)
func main() {
	fmt.Println(len("你好bj!"))
}

答:

考点:len函数的返回值,编码⻓度。
⼀个中⽂占三个字节。

结果:9

6.7 🍏实现函数

func main(){
	var num interface{} = 1.2345
 //使⽤reflect输出类型与值
}

答:

考点:反射
结果:

func main(){
var num float64 = 1.2345
	//使⽤reflect输出类型与值
	//类型
	fmt.Println(reflect.TypeOf(num))
	//值
	fmt.Println(reflect.ValueOf(num))
}

6.8 🍒编写⼀个函数,实现字符串反转,函数输⼊类型为string

示例:锄⽲⽇当午 转换后 午当⽇⽲锄
答:

考点:函数实现
结果:

func reverse(str string) string {
	rs := []rune(str)
	len := len(rs)
	var tt []rune
	tt = make([]rune, 0)
	for i := 0; i < len; i++ {
		tt = append(tt, rs[len-i-1])
	}
	return string(tt[0:])
}

func main(){
	str:="锄⽲⽇当午"
	reverse(str) 
}

以上是关于①★GO语言面试之数据格式舒适版♥√的主要内容,如果未能解决你的问题,请参考以下文章

Go语言之Go语言并发

边做算法边学go语言之程序员面试金典面试题 01.06. 字符串压缩

go语言之数据类型和格式化输出

打造超级舒适的Go开发环境之VIM配置

go语言调度器源代码情景分析之六:go汇编语言

Go语言之进阶篇爬百度贴吧并发版