最新golang语言面试题总结(三)

1、go中拼接字符串有几种方式

1、"+"

     最常用的方法就是,使用"+"将两个字符串进行连接,与Python类似,不过Go语言中的字符串是不可变的类型,因此用"+"进行连接会产生一个新的字符串,这样对效率会有所影响。

a := "字符串"
b := "拼接"
c := a+b
fmt.Print(c) //c = "打印字符串"

2、使用sprintf函数

           第二种方法,就是使用sprintf函数,虽然不会像直接使用+那样产生临时的字符串,但效率也不高。

a := "字符串"
b := "拼接"
c := fmt.Sprintf("%s%s", a, b) //c = "打印字符串"

3、使用Join函数

      第三种方法就是,使用Join函数,这里需要先引入strings包才能调用Join函数,此函数会先根据字符串数组的内容,计算出一个拼接之后的长度,然后申请对应大小的内存,一个一个字符串填入,在已有一个数组的情况下,这种效率会很高,如果没有的话效率也不高。

//需要先导入strings包
a := "字符串"
b := "拼接"
//定义一个字符串数组包含上述的字符串
var str []string = []string{a, b}
//调用Join函数
c := strings.Join(str, "")
fmt.Print(c)

4、调用buffer.WriteString函数

第四种方法就是,调用buffer.WriteString函数,此方法的性能要远远大于上面的方法。

//需要先导入bytes包
a := "字符串"
b := "拼接"
//定义Buffer类型
var bt bytes.Buffer
向bt中写入字符串
bt.WriteString(a)
bt.WriteString(b)
//获得拼接后的字符串
c := bt.String()

5、用buffer.Builder

第五种方法是用buffer.Builder,此方法和上面的差不多,不过官方建议使用这个,且使用方法和上面基本一样。

//需要先导入Strings包
a := "字符串"
b := "拼接"
var build strings.Builder
build.WriteString(a)
build.WriteString(b)
c := build.String()

2、go中"_"的作用

1、import中的下滑线

此时“_”的作用是:当导入一个包的时候,不需要把所有的包都导进来,只需要导入使用该包下的文件里所有的init()的函数。

package main
 
import _ "hello/imp"
 
func main() {
    //imp.Print() //编译报错,说:undefined: imp

2、下划线在代码中
作用是:下划线在代码中是忽略这个变量

也可以理解为占位符,那个位置上本应该赋某个值,但是我们不需要这个值,所以就把该值给下划线,意思是丢掉不要,这样编译器可以更好的优化,任何类型的单个值都可以丢给下划线。

如果方法返回两个值,只想要其中的一个结果,那另一个就用_占位
 

package main
 
import "fmt"
 
v1, v2, _ := function(...)

3、占位符

"_"是特殊标识符,用来忽略结果

3、使用go实现99乘法表

	for i := 1; i < 10; i++ {
		for j := 1; j <= i; j++ {
			fmt.Printf("%d*%d=%d ", j, i, i*j)
		}
		fmt.Println("")
	}

结果:
1*1=1 
1*2=2 2*2=4 
1*3=3 2*3=6 3*3=9 
1*4=4 2*4=8 3*4=12 4*4=16 
1*5=5 2*5=10 3*5=15 4*5=20 5*5=25 
1*6=6 2*6=12 3*6=18 4*6=24 5*6=30 6*6=36 
1*7=7 2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49 
1*8=8 2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64 
1*9=9 2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 9*9=81 

4、linux命令,查看端口占用,cpu负载,内存占用,如何发送信号给一个进程、修改文件权限

  Linux 查看端口占用情况:
     lsof -i:端口号
     netstat -tunlp | grep 端口号
  cpu负载:
     uptime
  内存占用:
     top
  如何发送信号给一个进程:
     1. kill() 函数
     2. alarm() 函数
  修改文件权限:
     chmod命令用于修改文件权限

5、Redis redo log, binlog 与 undo log

redo log是属于innoDB层面,binlog属于MySQL Server层面的,这样在数据库用别的存储引擎时可以达到一致性的要求。
redo log是物理日志,记录该数据页更新的内容;binlog是逻辑日志,记录的是这个更新语句的原始逻辑
redo log是循环写,日志空间大小固定;binlog是追加写,是指一份写到一定大小的时候会更换下一个文件,不会覆盖。
binlog可以作为恢复数据使用,主从复制搭建,redo log作为异常宕机或者介质故障后的数据恢复使用。

1.redo log通常是物理日志,记录的是数据页的物理修改,而不是某一行或某几行修改成怎样怎样,它用来恢复提交后的物理数据页(恢复数据页,且只能恢复到最后一次提交的位置)。
2.undo用来回滚行记录到某个版本。undo log一般是逻辑日志,根据每行记录进行记录。

6、使用三个协程,每秒钟打印cat dog fish

使用三个协程,每秒钟打印cat dog fish
注意:1、顺序不能变化(协程1打印cat,协程2打印dog,协程3打印fish)
     2、无限循环即可
/*
使用三个协程,每秒钟打印cat dog fish
注意:顺序不能变化(协程1打印cat,协程2打印dog,协程3打印fish)
无限循环即可
*/
func main() {
	wg := sync.WaitGroup{}
	wg.Add(3)
	chcat := make(chan int)
	chdog := make(chan int)
	chfish := make(chan int)
	go printCat(&wg, chcat, chfish)
	go printDog(&wg, chdog, chcat)
	go printfash(&wg, chfish, chdog)
	wg.Wait()
}
func printDog(wg *sync.WaitGroup, dog chan int, cat chan int) {
	defer wg.Done()
	for {
		<-cat
		fmt.Println("dog")
		time.Sleep(time.Second)
		dog <- 1
	}
}
func printCat(wg *sync.WaitGroup, cat chan int, fish chan int) {
	defer wg.Done()
	for {
		cat <- 1
		fmt.Println("cat")
		time.Sleep(time.Second)
		<-fish
	}
}
func printfash(wg *sync.WaitGroup, fish chan int, dog chan int) {
	defer wg.Done()
	for {
		<-dog
		fmt.Println("fish")
		time.Sleep(time.Second)
		fish <- 1
	}
}

7、Go出现panic的场景

go中发生panic的场景:
- 数组/切片越界
- 空指针调用。比如访问一个 nil 结构体指针的成员
- 过早关闭 HTTP 响应体
- 除以 0
- 向已经关闭的 channel 发送消息
- 重复关闭 channel
- 关闭未初始化的 channel
- 未初始化 map。注意访问 map 不存在的 key 不会 panic,而是返回 map 类型对应的零值,但是不能直接赋值
- 跨协程的 panic 处理
- sync 计数为负数。
- 类型断言不匹配。`var a interface{} = 1; fmt.Println(a.(string))` 会 panic,建议用 `s,ok := a.(string)`

8、Http是短连接还是长连接?

  • HTTP/1.0中,默认使用的其实是短连接。也就是说,浏览器和服务器每进行一次HTTP操作,就要建立一次连接,但任务结束后就会中断连接。如果客户端浏览器访问的某个HTML或其他类型的 Web页中包含有其他的Web资源,如JavaScript文件、图像文件、CSS文件等;当浏览器每遇到这样一个Web资源,就会建立一个HTTP会话;
  • 从HTTP/1.1起,默认使用长连接,用以保持会话的连接特性。使用长连接的HTTP协议,会在响应头中加入这行代码:Connection:keep-alive;
  • 在使用长连接的情况下,当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的 TCP连接不会关闭,如果客户端再次访问这个服务器上的网页,会继续使用这一条已经建立好的连接。但Keep-Alive也不会永久保持连接,它有一个保持时间,可以在不同的服务器软件(如Apache)中设定这个时间。我们要注意,实现长连接要客户端和服务端都支持长连接。
  •  TCP三次握手和四次挥手过程

    既然上面我们说到了三次握手和四次挥手,健哥就再扩展一下说说这两个操作的实现过程。

    三次握手:先向HTTP服务器发起TCP的确认请求

  • 客户端 --> SYN --> 服务器
  • 服务器 --> SYN+ACK --->客户端
  • 客户端 --> ACK --> 服务器
  • 四次挥手:客户端要和服务器断开TCP连接

  • 客户端 --> FIN +ACK ---> 服务器
  • 服务器 --
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值