Go 代码测试覆盖度

在 Go 语言中,本身提供了一些命令来展示代码的覆盖度,我们可以通过执行这些命令来查看哪些语句被测试覆盖到了,哪些没有,进而可以编写更多的 case 来提高代码的覆盖度。

执行下面的命令,可以得出项目里面所有 package 的覆盖度

1
go test ./... -cover
阅读更多

哈希函数

概念

什么是哈希函数?

定义其实很简单,哈希函数其实就是一种映射关系,它可以把任意长度的数据映射为固定长度的数据,输出一般称为摘要(digest) ,就比如常见的 md5 算法,可以将输入映射成 128 bits

$$\{0, 1\}^* \overset{map}{\longrightarrow} \{0,1\}^n$$

同时,也正因为说,哈希函数将任意长度的输入映射成固定长度的输出,因为输入空间远大于输出空间,所以必然会存在冲突,比如下面的这种情景。不过,在实际使用的时候,必须要求哈希函数具备一定的安全性。

阅读更多

Gin 快速上手

使用 Go 搭建 Web 后端,最简单的就是使用原生的 net/http 库了,下面是一个简单的例子:

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

import (
"fmt"
"net/http"
)

func greet(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Hello World!")
}

func main() {
http.HandleFunc("/", greet)
http.ListenAndServe(":8080", nil)
}

运行代码之后,便会在8080端口处监听,接收客户端的请求,然后返回响应,访问 http://localhost:8080 即可以访问到对应的内容。

阅读更多

Golang 选项模式

需求

Golang不支持在函数定义的时候声明默认值,也就是说我们不能够使用类似下面的代码

1
2
3
func New(addr string="localhost",  port string="8080"){
...
}

并且也不支持函数的重载,函数名不能够重复,无法根据需要的参数数量创建不同的函数形式,也就是我们不能使用下面的方式

1
2
3
4
5
6
7
func New(addr string){
...
}
// 再次使用同样的函数名会报错
func New(addr string, port string){
...
}
阅读更多

揭露切片的真实面目

本节主要内容位于 runtime/slice.go, 基于 go1.16.4/amd64

创建一个切片十分简单,如下即可创建一个长度为 10 的 int 切片

1
slice := make([]int, 10)

但是具体是如何实现的呢,我们慢慢来看。

slice 结构

slice.go 中首先定义的就是 slice 结构体

1
2
3
4
5
type slice struct {
array unsafe.Pointer
len int
cap int
}

这样一看,其实 slice 也不是那么神奇,结构体中包含了一个指向实际数据的指针array,以及切片的长度 len 和切片的容量 cap

切片作为参数进行传递的时候,传递的不是整个结构体,实际上是传入了 slice 中的 array 数据指针,如果在函数内部修改了切片,那么同样会修改外部的切片。

阅读更多

字符串与切片转换

本节内容主要代码位于 runtime/string.go, 基于 go1.16.4/amd64

以下面的代码进行说明

1
2
3
slice := []byte{'h', 'e', 'l', 'l', 'o'}
slice2str := string(slice)
str2slice := []byte(slice2str)

slice to string

底层将 byte slice 转换成 string 的函数为 slicebytetostring

1
func slicebytetostring(buf *tmpBuf, ptr *byte, n int) (str string) 

这个函数接收三个参数,*tmpBuf 是一个指向 byte 数组的指针,ptr 指向 slice 第一个元素的地址, n 表示切片的长度。

阅读更多

字符串相加

本节内容主要代码位于 runtime/string.go

以下面的代码进行说明

1
2
3
a := "Hello "
b := "World "
_ = a + b

当执行 a+b 的时候,底层上调用的是 concatstrings,并且将a, b 两个操作数作为 slice 传递进去,如下:

阅读更多

Golang 报错 package xxx is not in GOROOT or GOPATH 或者 cannot find package “xxx“ in any of

GO111MODULE=”off”

GO111MODULE="off" 的条件下,并且写的代码不在 $GOPATH/src 下,也就是说下面的 main.go 不在$GOPATH/src 目录下面,同时我想要使用当前项目目录下的另一个 module 里面的可导出标识符(函数、变量等),但是这个模块 不是标准库,或者说不在 GOROOT 里(一般我们不会修改 GOROOT 中的内容)

阅读更多