这是我参与「第三届青训营 -后端场」笔记创作活动的第1篇笔记
第一节课
fmt.Println: 用默认类型的格式将传入的参数写到标准输出 参数:字符串和变量 参数;字符串和变量之间用逗号间隔, 输出:用空格间隔
2、fmt.Printf: 用占位符将传入的变量写到标准输出 输入:占位符,变量 输出
3、fmt.Sprintf: 用占位符将传入的变量返回为字符串,不会在终端显示;
4、fmt.Sprintln:
用默认的类型格式将传入的参数返回为字符串,字符串和变量之间用空格间隔,不会在终端显示
for initialization; condition; post {
// zero or more statements
}
for循环三个部分不需括号包围。大括号强制要求,左大括号必须和post语句在同一行。
if num := 9; num < 0 {
fmt.Println(num, "is negative")
注意if后可以接短声明,强制左大括号位置
switch 后不加变量,case 里面用if else
switch 不需要加break
fmt.Println(m["11"]) // 0
r, ok := m["two"]
fmt.Println(r, ok) // 0 false
打印不存在的键的map,输出为0,r,ok对应的是值和是否存在对应的值
func (u *user) resetPassword(password string) {
u.password = password
}
a := user{name: "wang", password: "1024"}
a.resetPassword("2048")
结构体方法,注意结构体方法定义,这样实现类似于类的调用的效果
func main() {
str := "你好guoke"
rt := []rune(str)
fmt.Println("字符串长度为:", len(rt))
for i:=0; i<len(rt); i++{
fmt.Println("第",i+1,"个字符为:",string(rt[i]))
}
}
string是以byte数组形式存储的,而一个utf8格式的中文占3个byte.要得到正确的中文字符的长度和分割,可以使用rune数组来拆分. rune类型是int32的别名,一个rune可以表示一个中文字符,go也提供了rune数组自动拆分string中文字符的方法rt := []rune(str).
//为中间参数为0时可以识别,0x,0b(二进制) 0o(八进制) ,第三个参数是返回int64
n, _ = strconv.ParseInt("0x1000", 0, 64)
fmt.Println(n) // 4096
字符串转为inter64
buf, err := exec.Command("dir", "C:/Users/zzh/Desktop").CombinedOutput()
if err != nil {
panic(err)
}
fmt.Println(string(buf))
}
路径连接
//windows默认添加\r\n,因此需要处理两个,而不是一个
input = strings.TrimSuffix(input, "\r\n")
fmt.Println(input)
课上的代码在windows上运行会上面的问题
package main
import (
"fmt"
"io/ioutil"
"log"
"net/http"
"strings"
)
func main() {
client := &http.Client{}
var data = strings.NewReader(`{"trans_type":"en2zh","source":"good"}`)
req, err := http.NewRequest("POST", "https://api.interpreter.caiyunai.com/v1/dict", data)
if err != nil {
log.Fatal(err)
}
req.Header.Set("Accept", "application/json, text/plain, */*")
//省略,同上
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close() //用defer手动关闭resonse body流,会在函数运行结束之后执行
bodyText, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s\n", bodyText)
}
读取流
第二节课
- 在json的规范中,对于数字类型是不区分整形和浮点型的。
- 在使用json.Unmarshal进行json的反序列化的时候,如果没有指定数据类型,使用interface{}作为接收变量,其默认采用的float64作为其数字的接受类型
- 当数字的精度超过float能够表示的精度范围时就会造成精度丢失的问题
由于测试文件和其他文件是分开的,因此当使用go test 测试文件时,需要加入测试文件所加载的文件,举例如下:
//print.go
package test
func HelloTom() string {
return "Tom"
}
print_test.go
package test
import (
"github.com/stretchr/testify/assert"
"testing"
)
func TestHelloTom(t *testing.T) {
output := HelloTom()
expectOutput := "Tom"
assert.Equal(t, expectOutput, output)
}
//terminal
D:\go-project-example\test>go test print_test.go
# command-line-arguments [command-line-arguments.test]
.\print_test.go:9:12: undefined: HelloTom
FAIL command-line-arguments [build failed]
FAIL
D:\go-project-example\test>go test print_test.go print.go
ok command-line-arguments 0.058s
也能进入直接目录文件夹,使用go test -v 进行所有测试 go test go文件和test 文件 --cover 实现覆盖率测试 mock测试 摆脱本地文件的依赖和束缚 基准测试 进入直接目录 go test -bench=.
//关于WaitGroup的使用
func ManyGoWait() {
var wg sync.WaitGroup //1
wg.Add(5) //2
for i := 0; i < 5; i++ {
go func(j int) {
defer wg.Done() //3
hello(j) //4
}(i)
}
wg.Wait() //4
}
你只需要在调用普通函数或方法前加上关键字defer,就完成了defer所需要的语法。当执行到该条语句时,函数和参数表达式得到计算,但直到包含该defer语句的函数执行完毕时,defer后的函数才会被执行,不论包含defer语句的函数是通过return正常结束,还是由于panic导致的异常结束。你可以在一个函数中执行多条defer语句,它们的执行顺序与声明顺序相反。
补充
- GO111MODULE有三个值:off、on 和 auto(默认值) 在使用模块的时候,
GOPATH是无意义的,不过它还是会把下载的依赖储存在$GOPATH/src/mod中,也会把go install的结果放在$GOPATH/bin中。GO111MODULE=off,无模块支持,go 会从 GOPATH 和 vendor 文件夹寻找包GO111MODULE=on,模块支持,go 会忽略 GOPATH 和 vendor 文件夹,只根据go.mod下载依赖GO111MODULE=auto,在$GOPATH/src外面且根目录有go.mod文件时,开启模块支持go modThe commands are:downloaddownload modules to local cache (下载依赖的module到本地cache))
editedit go.mod from tools or scripts (编辑go.mod文件)graphprint module requirement graph (打印模块依赖图))initinitialize new module in current directory (再当前文件夹下初始化一个新的module, 创建go.mod文件))tidyadd missing and remove unused modules (增加丢失的module,去掉未用的module)
vendormake vendored copy of dependencies (将依赖复制到vendor下)verifyverify dependencies have expected content (校验依赖)whyexplain why packages or modules are needed (解释为什么需要依赖)假设你已经有了一个go 项目, 比如在$GOPATH/github.com/smallnest/rpcx下, 你可以使用go mod init github.com/smallnest/rpcx在这个文件夹下创建一个空的go.mod(只有第一行module github.com/smallnest/rpcx)。 然后你可以通过go get ./...让它查找依赖,并记录在go.mod文件中(你还可以指定-tags,这样可以把tags的依赖都查找到)。 通过go mod tidy也可以用来为go.mod增加丢失的依赖,删除不需要的依赖,但是我不确定它怎么处理tags。 执行上面的命令会把go.mod的latest版本换成实际的最新的版本,并且会生成一个go.sum记录每个依赖库的版本和哈希值。、go.mod 提供了module,require、replace和exclude四个命令
module语句指定包的名字(路径)require语句指定的依赖项模块replace语句可以替换依赖项模块exclude语句可以忽略依赖项模块
- 再次执行脚本
go run server.go发现跳过了检查并安装依赖的步骤。 - 可以使用命令
go list -m -u all来检查可以升级的package,使用go get -u need-upgrade-package升级后会将新的依赖版本更新,也可以使用go get -u升级所有依赖
总结
这两节课虽然还有一些细节不了解,但是已经让有了与在学校的课程内容截然不同的体验,尤其是测试这方面,我相信后面会逐步应用级的知识,而不是纯粹的理论。