实验途中通用配置及坑点记录。
环境
win下操作
windows下不能动态编译go.so, 会使得第一句 go build -race -buildmode=plugin ../mrapps/wc.go 就会报错。
因此使用wsl + vscode的方式。
wsl:通过windows下的终端安装。 注意点:
① 要升级到wsl2,否则后面可能报错。
② 国内命令行下载ubuntu超级慢,可通过win自带的微软store下载
vscode: 注意点:
① 在vscode里面下载remot-wsl插件
② 还要下go插件
③ vscode不能write在Ubuntu里的文件,改:
sudo find /home/ -type d -user root -exec sudo chown -R $USER: {} ;
本机传东西给ubuntu: 在虚拟机中端打开/mnt,ls c就是c盘,d就是d盘
go环境 配置
环境配置提示:一种方法是把6.824目录设置为$GOPATH;另一种方法是使用module的方式——在src目录下使用go mod init example.com/src
生成mod文件(网址和路径自己取,只要最后一层目录是src即可),然后把src代码中所有import ../mr替换成import 网址/src/mr。
export GOROOT=/usr/local/go //goroot就是安装go的文件夹
export GOPATH=/home/axun/6.824 // gopath就是当前运行的文件夹
export GO111MODULE=on
export PATH=$PATH:$GPROOT/bin:$GOPATH/bin
要么直接这样👆
要么 vim /etc/profile source /etc/profile
—————————— 如果项目import的路径是 6.824/mr
, 就是GO111MODULE=on export "GOPATH=$PWD"
如果是off, 就会报错 ../mrapps/wc.go:9:8: cannot find package "6.824/mr" in any of: /usr/local/go/src/6.824/mr (from $GOROOT) /home/Go/6.824/src/6.824/mr (from $GOPATH)
如果确认开启,那么 go 会到 你的 ...\go\pkg\mod
类似的目录下查找依赖。 而不是去到 ...\go\src
你的 gopath 路径查找依赖。
还要安装gcc
由于ubuntu默认没有gcc,导致go build -buildmode=plugin ../mrapps/wc.go
命令时候编译报错 sudo apt-get install build-essential
debug时没有插件,但是又墙了。改: GOPROXY="https://goproxy.io,direct"
然后要在goroot的bin下面下: go install -v github.com/go-delve/delve/cmd/dlv@latest
cannot load plugin wc.go
无法插件wc.so 有得救,加-gcflags="all=-N -l"
无法wc.go 无法救,手动调试罢了
函数
调试
mrworker.go
中注释描述通过 go run mrworker.go wc.so
来运行工作节点,不过如果构建 wc.so
时开启了竞争检测(-race),则运行 mrworker.go 时也同样需要开启竞争检测,否则会提示 cannot load plugin wc.so
,如果打印 err 则会显示 plugin.Open("wc"): plugin was built with a different version of package runtime
。
同样的,如果使用 GoLand 调试程序,由于在调试模式下 GoLand 编译 Go 文件时会增加 -gcflags="all=-N -l"
参数,所以也需要在打包 wc.so 时增加相同的参数。
输出 打印区别
Golang 格式化输出使用"fmt"包。 // 以下输出等效 // Println, 多个参数间自动插入空格,自动换行。【不能带%格式】 fmt.Println("Hello", 23)
// Print 和 Printf, 不自动插入空格,不自动换行
fmt.Print("Hello ", 23, "\n")
fmt.Printf("Hello %d\n", 23) // 【可以带%格式】
// Fprint 和 Fprintf, 不自动插入空格,不自动换行
fmt.Fprint(os.Stdout, "Hello ", 23, "\n")
fmt.Fprintf(os.Stdout, "Hello %d\n", 23)
// Sprint 和 Sprintf, 不输出,只返回字符串
// 注意:Sprintf转换字符串(%s)时,可能隐式调用String()方法,可能出现循环调用
fmt.Print(fmt.Sprint("Hello ", 23, "\n"))
fmt.Print(fmt.Sprintf("Hello %d\n", 23))
定时器函数
clock = time.NewTimer(100 * time.Second) // 定时100秒
time1 = time.Now()
t := <- clock.c //定时器有三个属性,此属性为通道,表示要等多长时间
time2 = time.Now() //如果运行了<- clock.c,就表示这一段儿已经计时了,time2到time1的时间就是定时的100s
time.reset(一个新时间) //定时器属性,重置计数
time.stop() //定时器属性,停止计时