Golang 每日一题 202303篇

每日一题,从问题出发,透过问题查漏补缺

Go每日一题 (变量定义)

定义一个包内全局字符串变量,下面语法正确的是(多选):

  • A. var str string
  • B. str := “”
  • C. str = “”
  • D. var str = “”

答案解析

答案及解析:AD。
B 只支持局部变量声明;C 是赋值,str 必须在这之前已经声明。

Go每日一题 (struct encoding/json 导出)

以下代码输出什么?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package main

import (
"encoding/json"
"fmt"
"time"
)

func main() {
t := struct {
time.Time
N int
}{
time.Date(2020, 12, 20, 0, 0, 0, 0, time.UTC),
5,
}

m, _ := json.Marshal(t)
fmt.Printf("%s", m)
}

答案解析

正确答案 B

如果值实现了 json.Marshaler 接口并且不是 nil 指针,则 Marshal 函数会调用其 MarshalJSON 方法以生成 JSON。如果不存在 MarshalJSON 方法,但该值实现 encoding.TextMarshaler 接口,则 Marshal 函数调用其 MarshalText 方法并将结果编码为 JSON 字符串。

Go每日一题 (defer)

下面这段代码输出什么?

1
2
3
4
5
6
7
8
func hello(i int) {  
fmt.Println(i)
}
func main() {
i := 5
defer hello(i)
i = i + 10
}

答案解析

答案及解析:5。
hello() 函数的参数在执行 defer 语句的时候会保存一份副本,在实际调用 hello() 函数时用,所以是 5.

Go每日一题 (结构体嵌套)

下面这段代码输出什么?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
type People struct{}

func (p *People) ShowA() {
fmt.Println("showA")
p.ShowB()
}
func (p *People) ShowB() {
fmt.Println("showB")
}

type Teacher struct {
People
}

func (t *Teacher) ShowB() {
fmt.Println("teacher showB")
}

func main() {
t := Teacher{}
t.ShowA()
}

答案解析

showA
showB

Teacher 没有自己 ShowA(),所以调用内部类型 People 的同名方法,
需要注意的是第 5 行代码调用的是 People 自己的 ShowB 方法。

Go每日一题 (字符串)

下列选项正确的是?

1
2
3
4
5
func main() {
str := "hello"
str[0] = 'x'
fmt.Println(str)
}
  • A. hello
  • B. xello
  • C. compilation error

答案解析

C
Go 语言中的字符串是只读的。

Go每日一题 (指针)

下面代码输出什么?

1
2
3
4
5
6
7
8
9
10
func incr(p *int) int {
*p++
return *p
}

func main() {
p := 1
incr(&p)
fmt.Println(p)
}
  • A. 1
  • B. 2
  • C. 3

答案解析

B
指针,incr() 函数里的 p 是 *int 类型的指针,指向的是 main() 函数的变量 p 的地址。
第 2 行代码是将该地址的值执行一个自增操作,incr() 返回自增后的结果。

Go每日一题 (可变函数)

对 add() 函数调用正确的是?

1
2
3
4
5
6
7
func add(args ...int) int {
sum := 0
for _, arg := range args {
sum += arg
}
return sum
}
  • A. add(1, 2)
  • B. add(1, 3, 7)
  • C. add([]int{1, 2})
  • D. add([]int{1, 3, 7}…)

答案解析

答案及解析:ABD。
可变函数

Go每日一题 (channel)

以下代码输出什么?

1
2
3
4
5
6
7
8
9
10
11
12
13
package main

import (
"fmt"
"time"
)

func main() {
ch1 := make(chan int)
go fmt.Println(<-ch1)
ch1 <- 5
time.Sleep(1 * time.Second)
}
  • A:5
  • B:不能编译
  • C:运行时死锁

答案解析

C
<-ch1 先执行再 调起; 运行时死锁

Go每日一题 (array slice)

  1. 以下代码输出什么?
1
2
3
4
5
6
7
8
9
10
package main

import (
"fmt"
)

func main() {
a := []int{2: 1}
fmt.Println(a)
}
  • A:编译错误;
  • B:[2 1];
  • C:[0 0 1];
  • D:[0 1]

答案解析: [0 0 1]

  1. 以下代码输出什么?
1
2
3
4
5
6
package main

func main() {
var x = []int{4: 44, 55, 66, 1: 77, 88}
println(len(x), x[2])
}
  • A:5 66;
  • B:5 88;
  • C:7 88;
  • D:以上都不对

答案解析: 7 88

答案解析

var x = []int{4: 44, 55, 66, 1: 77, 88}

var x = []int{4:44, 5:55, 6:66, 1:77, 2:88}

Go每日一题 (nil切片 空切片)

下面代码下划线处可以填入哪个选项?

1
2
3
4
5
6
7
8
9
func main() {
var s1 []int
var s2 = []int{}
if __ == nil {
fmt.Println("yes nil")
}else{
fmt.Println("no nil")
}
}
  • A. s1
  • B. s2
  • C. s1、s2 都可以

答案解析

答案及解析:A。
nil 切片和空切片。nil 切片和 nil 相等,一般用来表示一个不存在的切片;
空切片和 nil 不相等,表示一个空的集合。

答案及解析:C。
题目仅仅是可以填入,并没有说要走第一个分支
都可以填, s2 == nil 返回的是 false, s1 == nil 返回的是 true

Go每日一题 (强制类型转换)

下面这段代码输出什么?

1
2
3
4
func main() {  
i := 65
fmt.Println(string(i))
}
  • A. A
  • B. 65
  • C. compilation error

答案解析

答案及解析:A。
UTF-8 编码中,十进制数字 65 对应的符号是 A。

Go每日一题 (接口)

下面这段代码输出什么?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
type A interface {
ShowA() int
}

type B interface {
ShowB() int
}

type Work struct {
i int
}

func (w Work) ShowA() int {
return w.i + 10
}

func (w Work) ShowB() int {
return w.i + 20
}

func main() {
c := Work{3}
var a A = c
var b B = c
fmt.Println(a.ShowA())
fmt.Println(b.ShowB())
}

答案解析

答案及解析:13 23。
种类型实现多个接口,结构体 Work 分别实现了接口 A、B,
所以接口变量 a、b 调用各自的方法 ShowA() 和 ShowB(),输出 13、23。

Go每日一题 (slice)

切片 a、b、c 的长度和容量分别是多少?

1
2
3
4
5
6
func main() {
s := [3]int{1, 2, 3}
a := s[:0]
b := s[:2]
c := s[1:2:cap(s)]
}

答案解析

a、b、c 的长度和容量分别是 0 3、2 3、1 2

数组或切片的截取操作。
截取操作有带 2 个或者 3 个参数,形如:[i:j] 和 [i:j:k],
假设截取对象的底层数组长度为 l。在操作符 [i:j] 中,如果 i 省略,默认 0,如果 j 省略,默认底层数组的长度,
**截取得到的切片长度和容量计算方法是 j-il-i**。
操作符 [i:j:k],k 主要是用来限制切片的容量,但是不能大于数组的长度 l,截取得到的切片长度和容量计算方法是 j-i、k-i。

Go每日一题 (map)

下面代码中 A B 两处应该怎么修改才能顺利编译?

1
2
3
4
5
6
7
func main() {
var m map[string]int //A
m["a"] = 1
if v := m["b"]; v != nil { //B
fmt.Println(v)
}
}

答案解析

1
2
3
4
5
6
7
8
func main() {
m := make(map[string]int)
// 或 m := map[string]int{}
m["a"] = 1
if v,ok := m["b"]; ok {
fmt.Println(v)
}
}

Go每日一题 (接口的静态类型)

下面代码输出什么?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
type A interface {
ShowA() int
}

type B interface {
ShowB() int
}

type Work struct {
i int
}

func (w Work) ShowA() int {
return w.i + 10
}

func (w Work) ShowB() int {
return w.i + 20
}

func main() {
c := Work{3}
var a A = c
var b B = c
fmt.Println(a.ShowB())
fmt.Println(b.ShowA())
}
  • A. 23 13
  • B. compilation error

答案解析

答案及解析:B
接口的静态类型。a、b 具有相同的动态类型和动态值,分别是结构体 work 和 {3};a 的静态类型是 A,b 的静态类型是 B,
接口 A 不包括方法 ShowB(),接口 B 也不包括方法 ShowA(),编译报错。

Go每日一题 (Go101)

Go101 发布的一条 twitter。以下代码是否能正常运行,结果是?

1
2
3
4
5
6
7
package main

func main() {
v := new(int)
*v = 2
println(5/+-*v)
}

答案解析

-2
https://gitee.com/ilmself010cn/studygolang_daily/blob/master/daily/2023/03/16/README.md

Go每日一题 (类型 类型别名)

有下面 3 行代码:

1
2
3
4
// 32 位机器
var x int32 = 32.0
var y int = x
var z rune = x

它们是否能编译通过?为什么?

如果面试时问这道题,你需要想想面试官想考察你什么。

答案解析

  • 01 数字字面量

在 Go 语言中,字面量是无类型(untyped)的。无类型是什么意思?无类型意味着可以赋值给类似类型的变量或常量。

1
2
3
4
5
6
var a int64 = 32.0
var b int = 32.0
var c float32 = 32.0
var d complex64 = 32.0
var e byte = 32.0
var f rune = 32.0
  • 02 不同类型

int 类型在 32 位机器占 4 字节,64 位机器占 8 字节。所以,在 32 位机器上,int32 和 int 的内存占用和内存布局是完全一样的。
但 Go 语言不会做隐式类型转换,int 和 int32 是不同的类型,因此上题中 2)编译不通过。

  • 03 类型别名

很显然,rune 是 int32 的别名,因此题目中 3)也能编译通过。

1
2
3
4
5
6
7
8
9
// 32 位机器
var x int32 = 32.0
// 【正确】字面量是无类型(untyped)的,32.0 是无类型的浮点数字面量,因此它可以赋值给任意数字相关类型变量(或常量)

var y int = x
// 【错误】Go 语言不会做隐式类型转换,int 和 int32 是不同的类型,因此上题中 2)编译不通过。

var z rune = x
// 【正确】rune 是 int32 的别名,因此题目中 3)也能编译通过

Go每日一题 (多赋值)

下面代码中,x 已声明,y 没有声明,判断每条语句的对错。

  • x, _ := f()
  • x, _ = f()
  • x, y := f()
  • x, y = f()

答案解析

答案及解析:错、对、对、错。
变量的声明。
1.错,x 已经声明,不能使用 :=;
2.对;
3.对,当多值赋值时,:= 左边的变量无论声明与否都可以;
4.错,y 没有声明。

Go每日一题 (defer)

下面代码输出什么?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
func increaseA() int {
var i int
defer func() {
i++
}()
return i
}

func increaseB() (r int) {
defer func() {
r++
}()
return r
}

func main() {
fmt.Println(increaseA())
fmt.Println(increaseB())
}
  • A. 1 1
  • B. 0 1
  • C. 1 0
  • D. 0 0

答案解析

答案及解析:B。
increaseA() 的返回参数是匿名,increaseB() 是具名

Go每日一题 (defer 返回值)

f1()、f2()、f3() 函数分别返回什么?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
func f1() (r int) {
defer func() {
r++
}()
return 0
}


func f2() (r int) {
t := 5
defer func() {
t = t + 5
}()
return t
}


func f3() (r int) {
defer func(r int) {
r = r + 5
}(r)
return 1
}

答案解析

答案及解析:1 5 1。

Go每日一题 (闭包)

以下代码输出什么?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package main

import "fmt"

func app() func(string) string {
t := "Hi"
c := func(b string) string {
t = t + " " + b
return t
}
return c
}

func main() {
a := app()
b := app()
a("go")
fmt.Println(b("All"))
}
  • A:Hi All;
  • B:Hi go All;
  • C:Hi;
  • D:go All

答案解析

A
关于(函数)闭包,有几个关键点:

  • 函数是一等公民;
  • 闭包所处环境,可以引用环境里的值;

Go每日一题 (defer)

下面代码段输出什么?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
type Person struct {
age int
}

func main() {
person := &Person{28}

// 1.
defer fmt.Println(person.age)

// 2.
defer func(p *Person) {
fmt.Println(p.age)
}(person)

// 3.
defer func() {
fmt.Println(person.age)
}()

person.age = 29
}

答案解析

答案及解析:29 29 28。变量 person 是一个指针变量 。

  1. person.age 此时是将 28 当做 defer 函数的参数,会把 28 缓存在栈中,等到最后执行该 defer 语句的时候取出,即输出 28;
  2. defer 缓存的是结构体 Person{28} 的地址,最终 Person{28} 的 age 被重新赋值为 29,所以 defer 语句最后执行的时候,依靠缓存的地址取出的 age 便是 29,即输出 29;
  3. 很简单,闭包引用,输出 29;

又由于 defer 的执行顺序为先进后出,即 3 2 1,所以输出 29 29 28。

1
2
3
闭包引用输出 29
地址引用 29
输入固定值 28

Go每日一题 (defer)

下面这段代码正确的输出是什么?

1
2
3
4
5
6
7
8
9
func f() {
defer fmt.Println("D")
fmt.Println("F")
}

func main() {
f()
fmt.Println("M")
}
  • A. F M D
  • B. D F M
  • C. F D M

答案解析

参考答案及解析:C。
被调用函数里的 defer 语句在返回之前就会被执行

Go每日一题 (slice)

下面的两个切片声明中有什么区别?哪个更可取?

  • A. var a []int
  • B. a := []int{}

答案解析

答案及解析:第一种切片声明不会分配内存,优先选择。

Go每日一题 (interface 指针)

A、B、C、D 哪些选项有语法错误?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
}

答案解析

答案及解析:BD
函数参数为 interface{} 时可以接收任何类型的参数,包括用户自定义类型等,
即使是接收指针类型也用 interface{},而不是使用 *interface{}。

Go每日一题 (struct 指针)

下面 A、B 两处应该填入什么代码,才能确保顺利打印出结果?

1
2
3
4
5
6
7
8
9
10
11
12
type S struct {
m string
}

func f() *S {
return __ //A
}

func main() {
p := __ //B
fmt.Println(p.m) //print "foo"
}

答案解析

A. &S{“foo”}
B. *f() 或者 f()
B 处,如果填 *f(),则 p 是 S 类型;如果填 f(),则 p 是 *S 类型;不过都可以使用 p.m 取得结构体的成员。

Go每日一题 (常量表达式)

以下代码输出什么?

1
2
3
4
5
6
7
8
9
10
package main

import (
"fmt"
)

func main() {
var ans float64 = 15 + 25 + 5.2
fmt.Println(ans)
}
  • A:不能编译;
  • B:45;
  • C:45.2;
  • D:45.0

答案解析

正确答案:C。
常量表达式是指仅包含常量操作数,且是在编译的时候进行计算的。

Go每日一题 (string)

下面的代码有几处语法问题,各是什么?

1
2
3
4
5
6
7
8
9
10
11
package main
import (
"fmt"
)
func main() {
var x string = nil
if x == nil {
x = "default"
}
fmt.Println(x)
}

答案解析

golang 的字符串类型是不能赋值 nil 的,也不能跟 nil 比较。

Go每日一题 (defer)

return 之后的 defer 语句会执行吗,下面这段代码输出什么?

1
2
3
4
5
6
7
8
9
10
11
12
13
var a bool = true
func main() {
defer func(){
fmt.Println("1")
}()
if a == true {
fmt.Println("2")
return
}
defer func(){
fmt.Println("3")
}()
}

答案解析

答案及解析:2 1
defer 关键字后面的函数或者方法想要执行必须先注册,return 之后的 defer 是不能注册的, 也就不能执行后面的函数或方法。

Powered by Hexo and Hexo-theme-hiker

Copyright © 2017 - 2023 Keep It Simple And Stupid All Rights Reserved.

访客数 : | 访问量 :