【Golang语言社区】Golang语言面试题
最近在很多地方看到了golang的面试题,看到了很多人对Golang的面试题心存恐惧,也是为了复习基础,我把解题的过程总结下来。 面试题
package main
import (
"fmt"
)
func main() {
defer_call()
}
defer_call() {
defer func() { fmt.Println("打印前") }()
defer "打印中") }"打印后") }()
panic("触发异常")
}
考点:defer执行顺序 打印后
type student struct {
Name string
Age int
}
pase_student() {
m := make(map[string]*student)
stus := []student{
{Name: "zhou",Age: 24},{Name: "li",31);">23},0);">"wang",31);">22},}
for _,stu := range stus {
m[stu.Name] = &stu
}
}
考点:foreach range stus {
stu.Age = stu.Age+10
}
也是不可行的。 大家可以试试打印出来: // 错误写法
range stus {
m[stu.Name] = &stu
}
for k,v:=range m{
println(k,"=>",v.Name)
}
// 正确
for i:=0;i<len(stus);i++ {
m[stus[i].Name] = &stus[i]
}
考点:go执行的随机性和闭包 第二个go func中i是函数参数,与外部for中的i完全是两个变量。 尾部(i)将发生值拷贝,go func内部指向值拷贝地址。
type People struct{}
func (p *People) ShowA() {
fmt.Println("showA")
p.ShowB()
}
ShowB"showB")
}
type Teacher struct {
People
}
(t *Teacher) "teacher showB")
}
() {
t := Teacher{}
t.ShowA()
}
考点:go的组合继承 showA showB
1)
int_chan := chan int,1)
string_chan := string,31);">1)
int_chan <- 1
string_chan <- "hello"
select {
case value := <-int_chan:
fmt.Println(value)
case value := <-string_chan:
panic(value)
}
}
考点:select随机性 select 中只要有一个case能return,则立刻执行。 func calc(index string,a,168);">b int) int {
ret := a + b
fmt.Println(index,168);">b,ret)
return ret
}
func main() {
a := 1
b := 2
defer calc("1",calc("10",b))
a = 0
defer calc("2",0);">"20",168);">b = 1
}
考点:defer执行顺序 10 1 2 3
20 0 2
2 1 3 4
func main() {
s := make([]int,5)
s = append(s,3)
fmt.Println(s)
}
考点:make默认值和append [0 0 0 0 0 1 2 3] s := make([]0)
s = 1,31);">2,31);">3)
fmt.Println(s)//[1 2 3]
type UserAges struct {
ages string]int
sync.Mutex
}
(ua *UserAges) Add(name int) {
ua.Lock()
defer ua.Unlock()
ua.ages[name] = age
}
Getstring) int {
if age,ok := ua.ages[name]; ok {
return age
}
return -1
}
考点:map线程安全 int {
ua.Lock()
defer ua.Unlock()
return age
}
-1
}
9. 下面的迭代会有什么问题?
(set *threadSafeSet) Iter() <-chan interface{} {
ch := interface{})
() {
set.RLock()
for elem := range set.s {
ch <- elem
}
close(ch)
set.RUnlock()
}()
return ch
}
考点:chan缓存池 package main
import (
"sync"
"fmt"
)
//下面的迭代会有什么问题?
type threadSafeSet struct {
sync.RWMutex
s []interface{}
}
interface{} {
// ch := make(chan interface{}) // 解除注释看看!
ch := interface{},len(set.s))
() {
set.RLock()
for elem,value := range set.s {
ch <- elem
println("Iter:",elem,value)
}
close(ch)
set.RUnlock()
}()
return ch
}
() {
th:=threadSafeSet{
s:[]interface{}{"2"},}
v:=<-th.Iter()
fmt.Sprintf("%s%v",0);">"ch",v)
}
package main
import (
"fmt"
)
type People interface {
Speak(string) string
}
type Stduent struct{}
func (stu *Stduent) Speak(think string) (talk string) {
if think == "bitch" {
talk = "You are a good boy"
} else {
talk = "hi"
}
return
}
func main() {
var peo People = Stduent{}
think := "bitch"
fmt.Println(peo.Speak(think))
}
考点:golang的方法集
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")
}
}
考点:interface内部结构
type People interface {
Show()
}
他们的底层结构如下: type eface struct { //空接口
_type *_type //类型信息
data unsafe.Pointer //指向数据的指针(go语言中特殊的指针类型unsafe.Pointer类似于c语言中的void*)
}
iface //带有方法的接口
tab *itab //存储type信息还有结构实现方法的集合
data unsafe.Pointer _type struct {
size uintptr //类型大小
ptrdata uintptr //前缀持有所有指针的内存大小
hash uint32 //数据hash值
tflag tflag
align uint8 //对齐
fieldalign uint8 //嵌入结构体时的对齐
kind uint8 //kind 有些枚举值kind等于0是无效的
alg *typeAlg //函数指针数组,类型实现的所有方法
gcdata *byte
str nameOff
ptrToThis typeOff
}
itab struct {
inter *interfacetype //接口类型
_type *_type //结构类型
link *itab
bad int32
inhash int32
fun [1]uintptr //可变大小 方法集合
}
可以看出iface比eface 中间多了一层itab结构。 itab 存储_type信息和[]fun方法集,从上面的结构我们就可得出,因为data指向了nil 并不代表interface 是nil, 所以返回值并不为空,这里的fun(方法集)定义了接口的接收规则,在编译的过程中需要验证是否实现接口 结果: BBBBBBB () {
i := GetValue()
switch i.(type) {
case int:
"int")
string:
"string")
interface{}:
"interface")
default:
"unknown")
}
}
GetValue() 解析
解析 14.是否可以编译通过?如果通过,输出什么? package main
() {
println(DeferFunc1(1))
println(DeferFunc2(println(DeferFunc3(1))
}
DeferFunc1int) (t int) {
t = i
defer () {
t += 3
}()
return t
}
DeferFunc2int) int {
t := i
DeferFunc3int) {
() {
t += i
}()
2
}
解析 15.是否可以编译通过?如果通过,输出什么? main() {
list := new([]int)
list = append(list,1)
fmt.Println(list)
}
解析 16.是否可以编译通过?如果通过,输出什么? import "fmt"
() {
s1 := []int{3}
s2 := []4,31);">5}
s1 = append(s1,s2)
fmt.Println(s1)
}
解析 17.是否可以编译通过?如果通过,输出什么? () {
sn1 := struct {
age int
name string
}{age: 11,name: "qq"}
sn2 := "qq"}
if sn1 == sn2 {
fmt.Println("sn1 == sn2")
}
sm1 := struct {
age int
m string{"a": "1"}}
sm2 := "1"}}
if sm1 == sm2 {
fmt.Println("sm1 == sm2")
}
}
解析 sn3:= struct {
name string
age int
}{age:"qq"}
sn3与sn1就不是相同的结构体了,不能比较。 还有一点需要注意的是结构体是相同的,但是结构体属性中有不可以比较的类型,如map,slice。 如果该结构属性都是可以比较的,那么就可以使用“==”进行比较操作。 可以使用reflect.DeepEqual进行比较 if reflect.DeepEqual(sn1,sm) {
fmt.Println("sn1 ==sm")
}else {
fmt."sn1 !=sm")
}
所以编译不通过: 18.是否可以编译通过?如果通过,输出什么? Foo(x interface{}) {
if x == "empty interface")
return
}
fmt.Println("non-empty interface")
}
() {
var x *int = nil
Foo(x)
}
解析 non-empty interface (m int](bool) {
if _,exist := m[id]; exist {
return "存在数据",31);">true
}
return nil,31);">false
}
() {
intmap:=string{
1:"a",31);">2:"bb",31);">3:"ccc",}
v,err:=GetValue(intmap,31);">3)
fmt.Println(v,err)
}
解析 20.是否可以编译通过?如果通过,输出什么? const (
x = iota
y
z = "zz"
k
p = iota
)
() {
fmt.Println(x,y,z,k,p)
}
解析 0 1 zz zz 4 21.编译执行下面代码会出现什么? package main
var(
size :=1024
max_size = size*2
)
() {
println(size,max_size)
}
解析 定义变量同时显式初始化 syntax error: unexpected := const cl = 100
var bl = 123
println(&bl,bl)
println(&cl,cl)
}
解析 cannot take the address of cl () {
0;i<10 ;i++ {
loop:
println(i)
}
goto loop
}
解析 goto loop jumps into block starting at 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)
}
解析 结果: cannot use i (type int) as type MyInt1 in assignment "fmt"
type User struct {
} type MyUser1 User type MyUser2 = User func (i MyUser1) m1(){
fmt.Println("MyUser1.m1")
}
func (i User) m2(){
fmt.Println("User.m2")
}
func main() {
var i1 MyUser1
var i2 MyUser2
i1.m1()
i2.m2()
}
解析 i1.m2() MyUser1.m1
User.m2
26.编译执行下面代码会出现什么? package main
import type T1 struct {
}
func (t T1) m1(){
fmt.Println("T1.m1")
} type T2 = T1 type MyStruct struct {
T1
T2
}
func main() {
my:=MyStruct{}
my.m1()
}
解析 ambiguous selector my.m1 my.T1.m1()
my.T2.m1()
type alias的定义,本质上是一样的类型,只是起了一个别名,源类型怎么用,别名类型也怎么用,保留源类型的所有方法、字段等。 27.编译执行下面代码会出现什么? "errors"
"fmt"
)
var ErrDidNotWork = errors.New("did not work")
DoTheThing(reallyDoIt bool) (err error) {
if reallyDoIt {
result,err := tryTheThing()
if err != nil || result != "it worked" {
err = ErrDidNotWork
}
}
return err
}
tryTheThing() "",ErrDidNotWork
}
() {
fmt.Println(DoTheThing(true))
fmt.Println(DoTheThing(false))
}
解析 var result string
return err
}
28.编译执行下面代码会出现什么?
test() []func() {
var funs []for i:=0;i<2 ;i++ {
funs = append(funs,() {
println(&i,i)
})
}
return funs
}
(){
funs:=test()
range funs{
f()
}
}
解析 0xc042046000 2 () []()
2 ;i++ {
x:=i
funs = append(funs,31);">println(&x,x)
})
}
return funs
}
29.编译执行下面代码会出现什么?
package main
(x int) ((),31);">()) {
return () {
println(x)
x+=10
},31);">println(x)
}
}
() {
a,b:=test(100)
a()
b()
}
解析 100 "fmt"
"reflect"
)
main1() {
if err:=recover();err!=nil{
fmt.Println(err)
}else {
fmt.Println("fatal")
}
}()
panic("defer panic")
}()
"panic")
}
() {
nil{
fmt.Println("++++")
f:=err.(()string) (err,f(),reflect.TypeOf(err).Kind().String()) }else {
fmt.Println("fatal")
}
}()
panic(string {
return "defer panic"
})
}()
"panic")
}
解析 defer panic (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- 《PHP框架之ThinkPHP项目CMS内容管理系统》全部20讲
- 为什么delphi ide会增加windows平台的计时器分辨率?
- ScriptException[scripts of type [inline], operation [up
- 在DirectX 3D中使用CEGUI
- 在golang中使用leveldb
- spring – 为超级类中没有@Autowired的@Repository bean注
- [VB.NET]有人用过API CreateFileMapping 内存共享 没有?能
- 如何使用Perl在后续订单中获取所有可能的相邻项组合?
- Golang适合高并发场景的原因分析
- Java:Spring:阅读spring context.xml时出现XML冲突重复定