Go语言练习题


title: Go语言练习题
tags: Go
author: Clown95


Go基础编程

Go初体验

  1. 熟悉go的编译环境已经编译过程,根据Hello World输出,拓展打印出自我介绍。

  2. 查询资料了解go语言的特点并简单的叙述。

  3. 一个包是否可以在一个源文件里面多次引用?

基础结构和类型

  1. 以下变量名有哪些是不合法的?

1a、abc、a&b 、年龄、 var、bool 、public、a2 、2#、a2_1、f unction、class、new

  1. 以下变量声明哪些条款是正确的?
	var i =1
	var i int
	var i = int
	i := 1
	i = 1
  1. 阅读以下代码,写出输出结果。
package main
import "fmt"
func main(){
	var a int =10
	fmt.Println(a)
	{
		a:=9
		fmt.Println(a)
	}
	fmt.Println(a)
}
  1. 编程实现:使用itoaconst,定义一周的数值,如Monday=1 ,Tuesday=2,依次类推Sunday=7。

  2. 编程实现:实现字符串"123"和整数123之间的互转,并格式化输出他们转换后的类型和值。

  3. 编程实现:使用类型别名,让go语言支持中文关键字,如 int可以用整数型替代。

输入输出

  1. 编程实现:声明一组变量:姓名(Name),年龄(Age),籍贯(From),专业(Major),从控制台接收内容并赋值给这些变量,最后输出这些变量的值。

  2. 简述内置的print和println函数与fmt和log标准库包中相应的打印函数有什么区别?

  3. 以下代码,输出结果会出现什么问题?如何解决?

func main() {
	
	for i := 0; i < 5; i++ {
		fmt.Println("请输入一个字符")
		var  code byte
		fmt.Scanf("%c",&code)
		fmt.Println(code)

	}
}

表达式与运算符

  1. 不依靠程序计算 (1+6)/2*4^2+10%3<<2的值

  2. 写出下面代码输出的内容(%4b是4位二进制)。

const(
	read byte=1 << iota
	write
	exec
	freeze
)
func main(){
	a:=read|write|freeze
	b:=read|freeze|exec
	c:= a &^b
	fmt.Printf("%4b &^ %4b= %04b\n", a, b, c)
}
  1. 编程实现:现有一个四位数, 计算它每位数的和、每位数的乘积 ,并用乘积除以和,输出它们的结果。

  2. 什么是byte?什么是rune? 如何将[]byte[]rune类型的值转换为字符串?

数组

  1. 以下不能正确定义数组和赋初值的语句是
var a=[5]int{1,2,3,4,5}
var b=[...]int{1,2,3,4,5}
var c[5]int={1,2,3,4,5}
var d=[5]int(2: 4,4:61}
  1. 编程实现:有一个长度为5的int数组,初始化该数组并计算平均值。

  2. 执行以下代码将会出现什么样的结果?怎么让它正确运行?

 var arr []int
 arr[0] =1
 fmt.Println(arr[0])

切片

  1. 关于整型切片的初始化,下面正确的有哪些?
s := make([]int){1,2,3,4}
s := make([]int, 0)
s := make([]int, 5, 10)
s := []int{1, 2, 3, 4, 5}
  1. 编程实现:花样体操比赛,6个评委打分,运动员的成绩去掉一个最高分,去掉一个最低分,剩下的4个分数的平均分就是最后得分,要求:
    (1)请把最高分,最低分的评委。(需要考虑存在多个最低分和最高分的情况)
    (2)找出最佳评委和最差评委。最佳评委是最后得分差距最小,最差评委最后得分差距最大。

  2. 编程实现:切片的升序排序,反转,搜索功能。

  3. 请简述切片和数组的区别。

Map

  1. 编程实现:现有字典map1的键是string型,值是int型,初始化为[psw1:123 psw2:456 psw3:789],要求删除键值对psw2:456,增加键值对psw4:135。

  2. 编程实现:实现一个函数,计算字符串的单词的个数,它应该返回一个包含字符串中单词个数的map。

  3. 为什么映射元素不可被取地址?

struct

  1. 编程实现:实现一个同学录,建立学生信息的结构体Student,每个学生的信息包括姓名()、性别、年龄。实现学生信息的添加、修改、删除、查询等功能。

  2. go语言中哪些类型的值可以被取地址,哪些不可以被取地址?

  3. 罗列出哪些类型不支持比较?

  4. 下面的变量a和b相等吗?变量c和d相等吗?

	a := struct{}{}
	b := struct{}{}
	c := [10]struct{}{}
	d := [10]struct{}{}
  1. 为什么两个nil值有时候会不相等?

  2. 简述go语言中make和new的区别。

  3. 哪些类型是值类型,那些是引用类型?

  4. 以下代码有什么问题,说明原因并修改代码得到预期结果。


type student struct {
	Name string
	Age  int
}

func main() {
	m := make(map[string]*student)
	stus := []student{
		{Name: "zhou", Age: 24},
		{Name: "li", Age: 23},
		{Name: "wang", Age: 22},
	}
	for _, stu := range stus {
		m[stu.Name] = &stu
	}

	fmt.Println(m)
}

指针类型

  1. 通过指针变量 p 访问其成员变量 name,下面语法正确的哪些?
p.name
(*p).name
(&p).name
p->name
  1. 填写A行和B行的空白,以确保打印输出为“foo”
package main

type S struct {
	m string
}

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

func main() {
	p := __    //B
	print(p.m) //print "foo"
}
  1. 执行以下代码时将打印什么?
func main() {
	s := "123"
	ps := &s
	b := []byte(*ps)
	pb := &b

	s += "4"
	*ps += "5"
	b[1] = '0'
	println(*ps," ",string(*pb))
}
  1. 解释为什么下面的打印输出是333,并修改A行以确保打印012。
package main
const N = 3
func main() {
	m := make(map[int]*int)
	for i := 0; i < N; i++ {
		m[i] = &i //A
	}
	for _, v := range m {
		print(*v)
	}
}

  1. 函数返回局部变量的指针是否安全?

流程控制

条件判断

  1. 编程实现:从控制台输入学生的成绩并判断等级,0-59 不及格,60-79 良好 ,80-100 优秀,使用if 和switch两种方法实现。

  2. 编程实现:从键盘接收一个整数,求奖金提成,规则:低于或等于10万元时,奖金可提10%;利润高于10万元,低于20万元时,低于10万元的部分按10%提成,高于10万元的部分,可提成7.5%;20万到40万之间时,高于20万元的部分,可提成5%;40万到60万之间时高于40万元的部分,可提成3%;60万到100万之间时,高于60万元的部分,可提成1.5%;高于100万元时,超过100万元的部分按1%提成从键盘输入当月利润,求应发放奖金总数?

  3. 编程实现:输入一个字符,判断它如果是小写字母输出其对应的大写字母;如果是大写字母输出其对应的小写字母;如果是数字输出数字本身;如果是空格输出“SPACE”;如果不是上述情况输出“Other”。(可用ASCII码判断)

  4. 下面的代码将会输出什么?

package main

import "fmt"

func False() bool {
	return false
}

func main() {
	switch False() {
	case true:
		fmt.Println("true")
	case false:
		fmt.Println("false")
	}
}
  1. switch流程控制代码块中的case表达式能重复吗?

循环结构

  1. 编程实现:从键盘输入字符串str,使用for range语句遍历该字符串中的每一个字符,并打印输出。

  2. 执行以下代码时将打印什么?

package main

import (
	"fmt"
)
func main() {
	s := []int{1, 2, 3}
	ss := s[1:]
	ss = append(ss, 4)
	for _, v := range ss {
		v += 10
	}
	for i := range ss {
		ss[i] += 10
	}
	fmt.Println(s)
}

  1. 编程实现:FizzBuzz是英国学校里常玩的游戏,从1数到100,如果遇见了3的倍数要说Fizz,如果遇见了5的倍数要说Buzz,如果既是3的倍数又是5的倍数要说FizzBuzz。编写一个程序,按游戏要求打印数字1-100。

  2. 编程实现:打印出所有的“水仙花数”,所谓“水仙花数”是指一个三位数,其各位数字立方和等于该数本身。例如,153是一个水仙花数,因为153=13+53+33。

  3. 编程实现:完成一个猜数字小游戏,要求:当用户输入的数字大于随机数时候,提示用户输入数字大了,反之提示用户数字小了,当用户在5次内都没有猜对,打印正确结果。并且额外添加成绩判定功能,当用户一次猜对结果,评定为S ,当用户在2-3次内猜对结果,评定为A,当用户在4-5次内猜对结果,评定为B, 一次都没有猜中,评定为C。

  4. 编程实现:求 5X+2Y+Z=50 的所有非负整数解。

函数

  1. 编程实现:已知三角形三边a、b、c,编写函数求三角形面积公式area(),求三角形面积。(三角形面积公式为area=√s(s-a)(s-b)(s-c),s为周长一半)。

  2. 编程实现:两种匿名函数,要求:
    (1)函数一,可以传参任意数量的int变量,计算这些参数的和并返回给某个变量。
    (2)函数二,传参int类型切片,计算切片内元素的和并返给某个变量。

  3. 编程实现:完成函数fac(),使用递归调用计算n的阶乘。

  4. 编程实现:函数FindInt(),功能:实现从一个指定位置找出字节切片中的整型数字,并返回该整数和下一个数的索引数的索引位置。(提示:使用ASCII码判断)

  5. 以下代码,最终打印的结果是什么?

package main
import "fmt"
func main() {
	defer fmt.Println(1)
	defer fmt.Println(2)
    fmt.Println(3)
	defer fmt.Println(4)
}
  1. 简述当多个包中含有init()函数,它的执行顺序是什么?

  2. 假设声明x并且未声明y,则下面哪些声明是正确的?

x, _ := f()
x, _ = f()
x, y := f()
x, y = f()
  1. 简要描述go中的main和init函数的区别。

  2. 简述下闭包的生命周期和作用范围。

go面向对象

  1. go语言是一个面向对象语言吗?

  2. 编程实现:定义一个People结构体,具有姓名(name)、年龄(age)、性别(Sex)等属性。要求:
    (1)封装set() 和get()函数,主要功能是设置Person对象属性和得到Person对象的属性,访问权限设置为私有
    (2)封装Show()函数,主要功能是打印Person对象信息,访问权限设置为公共。

  3. 编程实现:定义 Student结构体,继承上题的People结构体,并添加学号和专业等属性。并且设置Student的 set()、get()和Show()函数。

  4. 编程实现:定义一个任意类型键值对的Map,初始化并打印该Map,使用空接口 interface{}定义键值对数据类型。

  5. 编程实现:有一批图书,每本书有书名(name)、作者( author)、书号(isdn)、出版日期(date)4项数据,希望既可以通过书名查询,也可以使用作者或书号来查询图书。编写方法来实现此功能,如果查到,打印出此书的书名、作者、书号和出版日期信息。如果查不到此书,则打印出“无此书”。

  6. 对任意的非指针和非接口定义类型T,为什么类型*T的方法集总是类型T的方法集的超集,但是反之却不然?

  7. 以下代码编译能否通过?为什么?

package main
import (
	"fmt"
)
type People interface {
	Speak(string) string
}
type Stduent struct{}
func (stu *Stduent) Speak(think string) (talk string) {
	if think == "good" {
		talk = "You are a good boy"
	} else {
		talk = "hi"
	}
	return
}
func main() {
	var peo People = Stduent{}
	think := "good"
	fmt.Println(peo.Speak(think))
}

类型断言

  1. 下面的代码是否能够正确运行?如果不能请修改代码。
package main
import "fmt"

func echoArray(a interface{}){
  for _,v:=range a{
    fmt.Print(v," ")
  }
  fmt.Println()
  return
}
func main(){
  a:=[]int{2,1,3,5,4}
  echoArray(a)
}
  1. 定义一个容量为8的空接口 Slice,并进行初始化,然后使用 Comma-ok断言推断,Slice中各元素的数据类型。

Go软件工程

异常处理

  1. 执行以下代码时将打印什么?
package main

func f1() {
	defer println("f1-begin")
	f2()
	defer println("f1-end")
}

func f2() {
	defer println("f2-begin")
	f3()
	defer println("f2-end")
}

func f3() {
	defer println("f3-begin")
	panic(0)
	defer println("f3-end")
}

func main() {
	f1()
}
  1. 执行以下代码时将打印什么?退出代码是什么?
package main

import "log"

func f() {
	defer func() {
		if r := recover() r != nil {
			log.Printf("recover:%#v", r)
		}
	}()
	panic(1)
	panic(2)
}

func main() {
	f()
}

  1. 使用panic 和 recover机制编写一个检测用户账号合法性的程序,比如用户中不能出现空格,不能出现非法字符,比如‘,’、’#’、’!'等。

  2. 关于异常设计,下面说法正确的是()
    A. 在程序开发阶段,坚持速错,让程序异常崩溃
    B. 在程序部署后,应恢复异常避免程序终止
    C. 一切皆错误,不用进行异常设计
    D. 对于不应该出现的分支,使用异常处理

  3. 罗列出在go语言中哪些行为会触发异常,不少于3种。

测试

  1. 每个测试文件必须以什么结尾?每个测试文件必须导入什么包?功能测试函数必须以什么开头?

  2. 要执行压力测试需要带上什么参数?

  3. 在压力测试用例中,要在循环体内使用什么?以使测试可以正常的运行。

标准库

字符串操作

  1. 使用go语言实现网络流传价值一个亿Python的AI代码。

  2. 通过键盘输入英文字符串,并统计字符串中的英文字母的个数,同时输出字符串字节长度.

时间与日期

  1. 有字符串"2020-10-1 22:00:00",要求:把该字符串解析为Time格式,并计算和今天的时差。(注意时区)

  2. 函数调用time.Sleep(d)和数据通道接收<-time.After(d)操作之间有何区别?

flag

  1. 填写A行和B行的空白,解析ip和port的终端参数,默认值为0.0.0.0和8000。
package main

import "flag"
import "fmt"

var ip string
var port int

func init() {
	// A
	// B
}

func main() {
	flag.Parse()
	fmt.Printf("%s:%d", ip, port)
}

文件操作

  1. 使用Flag包,从控制台接收参数,完成文件的创建,写入,读取,删除 ,拷贝等操作。

  2. 编程实现:使用Go语言动态打印歌词,假设有以下类似lrc歌词文件,读取lrc文件,根据[]里面的时间动态的输出歌词。

[00:00.00]青花瓷 - 周杰伦
[00:20.89]素胚勾勒出青花笔锋浓转淡
[00:25.58]瓶身描绘的牡丹一如你初妆
[00:29.96]冉冉檀香透过窗心事我了然
[00:34.43]宣纸上 走笔至此搁一半
[00:38.99]釉色渲染仕女图韵味被私藏
[00:43.33]而你嫣然的一笑如含苞待放
[00:47.80]你的美一缕飘散
[00:50.27]去到我去不了的地方
[00:56.40]天青色等烟雨 而我在等你
[01:00.43]炊烟袅袅升起 隔江千万里
[01:05.34]在瓶底书汉隶仿前朝的飘逸
[01:09.37]就当我为遇见你伏笔

JSON解析

  1. 假设我们有如下一个结构体student,及其一个实例对象st,现在我们需要把这个结构体的一个对象st转换为JSON格式。
type Student struct {
	StuID   string
    Name    string
    Age     int
    Classes []string
    money   float32
}
st := &Student {
	"Go0001"
    "Xiao Ming",
    20,
    []string{"Math", "English", "Chinese"},
     99.99,
}
  1. 编程实现:根据现有的Api ( https://www.sojson.com/blog/305.html ),制作天气预报表,表格打印可以使用github.com/modood/table

注意因为接口有访问限制,如果你不太熟悉,建议把json返回信息先保存在文本中测试

查询的城市:北京
┌────────────────┬─────────┬────────────────┬────────────────┬────────┬─────┬───────────┬────────┬────────┬──────────────────────────────────────┐
│ Date           │ Sunrise │ High           │ Low            │ Sunset │ Aqi │ Fx        │ Fl     │ Type   │ Notice                               │
├────────────────┼─────────┼────────────────┼────────────────┼────────┼─────┼───────────┼────────┼────────┼──────────────────────────────────────┤
│ 28日星期一     │ 04:51   │ 高温 30.0℃     │ 低温 16.0℃     │ 19:33  │ 51  │ 西北风    │ 4-5级  │ 晴     │ 愿你拥有比阳光明媚的心情             │
│ 29日星期二     │ 04:50   │ 高温 30.0℃     │ 低温 16.0℃     │ 19:34  │ 49  │ 西风      │ <3级   │ 多云   │ 阴晴之间,谨防紫外线侵扰             │
│ 30日星期三     │ 04:50   │ 高温 33.0℃     │ 低温 19.0℃     │ 19:34  │ 39  │ 西南风    │ <3级   │ 晴     │ 愿你拥有比阳光明媚的心情             │
│ 31日星期四     │ 04:49   │ 高温 34.0℃     │ 低温 20.0℃     │ 19:35  │ 41  │ 西南风    │ <3级   │ 晴     │ 愿你拥有比阳光明媚的心情             │
│ 01日星期五     │ 04:49   │ 高温 35.0℃     │ 低温 20.0℃     │ 19:36  │ 74  │ 西南风    │ <3级   │ 晴     │ 愿你拥有比阳光明媚的心情             │
└────────────────┴─────────┴────────────────┴────────────────┴────────┴─────┴───────────┴────────┴────────┴──────────────────────────────────────

正则表达式

  1. 编程实现:使用正则表达式提取以下文本中的 邮箱账号 手机号 和网址
[email protected]|1802188880$http:\\wwww.baidu.com
  1. 编程实现:实现一个简单的爬虫程序,爬取百度go语言关键字的搜索结果,使用正则表达式获取每个结果的超链接地址。

反射

  1. 编程实现:List是个切片类型(List := make([]interface{},3),现有以下的数据,要求使用反射筛选出各类型的数据。
List[0] ="123"
List[1] =13579
List[2] =20.2
List[3] =Person{"小明",18}

  1. 编程实现:每个学生的信息包括学号(num)、姓名(name)、性别(sex)、成绩( score),请定义学生信息结构体对象 student,并初始化。最后要求使用反射原理修改学生基本信息,并输出修改后的结果。

  2. 解释为什么打印输出是false?修改A行以确保打印输出true

package main
import (
	"fmt"
	"reflect"
)
type S struct {
	a, b, c string
}
func main() {
	x := interface{}(&S{"a", "b", "c"})
	y := interface{}(&S{"a", "b", "c"})
	fmt.Println( x == y) //A
}

go并发与通信

协程goroutine

  1. 简述 线程和协程之间的区别。

  2. 编程实现:协程交替执行,使其能顺序输出1-20的自然数。

  3. 如何限制goroutine的创建数量?

  4. 如何等待所有goroutine的退出?

  5. goroutine是怎么样调度的?

通道channel

  1. 编程实现:使用channel实现斐波那契数列。

  2. 编程实现:使用for循环10次,打印出计数器i的值,要求:main调用的函数是一个goroutine并且使用channel通讯,不用关心goroutine是如何停止的。

  3. 编程实现:对上面一题进行拓展,使用两个channel和select,另一个channel用于状态判断,实程序正常运行。

  4. select可以用于什么?

  5. 无缓冲和缓冲通道之间有什么区别?

  6. 关于channel的特性,下面说法正确的是()
    A. 给一个 nil channel 发送数据,造成永远阻塞
    B. 从一个 nil channel 接收数据,造成永远阻塞
    C. 给一个已经关闭的 channel 发送数据,引起 panic
    D. 从一个已经关闭的 channel 接收数据,如果缓冲区中为空,则返回一个零值
    E. 无缓冲的channel和有缓冲的channel都是非同步的
    F. 无缓冲的channel是同步的,而有缓冲的channel是非同步的

  7. goroutine的泄漏怎么处理?

锁与同步

  1. 执行以下代码时将打印什么?并解决问题以确保len(m)打印为10。
package main

import (
	"sync"
)
const N = 10

func main() {
	m := make(map[int]int)

	wg := &sync.WaitGroup{}
	mu := &sync.Mutex{}
	wg.Add(N)
	for i := 0; i < N; i++ {
		go func() {
			defer wg.Done()
			mu.Lock()
			m[i] = i
			mu.Unlock()
		}()
	}
	wg.Wait()
	println(len(m))
}
  1. 编程实现:使用读写锁实现一个安全Map,下面代码是安全Map的实现,要求:实现这个Map的 存储操作 获取操作 删除操作 遍历Map
type SynchronizedMap struct {
	rw *sync.RWMutex
	data map[interface{}]interface{}
}
  1. 如何实现消息队列(多生产者,多消费者)?

原子操作

  1. 编程实现:使用add原子操作来并发地递增一个int32值。创建1000个新协程。每个新协程将整数n的值增加1。 原子操作保证这1000个新协程之间不会发生数据竞争,最终程序打印1000。

  2. 什么是乐观锁?什么是悲观锁?各自的应用场景是什么?

  3. 赋值是原子操作吗?

  4. 64位整数值的地址是否能保证总是64位对齐的,以便可以被安全地原子访问?

你可能感兴趣的:(go)