Go初体验
背景
我不是程序员,只是偶尔用Python写一些对个人有些帮助的小程序。之前了解过Go,朋友也一直在推荐Go,但一直没有深入研究过,自从面对下面几个事后,就萌生了想尝试一下的想法:
- 我想用Caddy搭一个简易HTTP Server,一般建议Docker部署,比较方便,但发现macOS如果需要支持Docker,需要装Docker虚拟机,光虚拟机就占了1.5g的内存。后来我去Caddy官网下载了支持ARM架构的Caddy,只有小40m左右,下载即可执行,不需要任何环境,此程序是用Go编译而成的,关于Caddy在macOS的使用,可以看这里;
- Java也是编译语言,可是要想执行,仍然需要Java虚拟机提供运行时环境;类比Python类似,是编译+解释语言,需要Python环境才能进行解释运行;
- 我需要对多个地址发送ICMP探测报文,Terminal其实挺好用的,只是为了多个地址,需要打开多个窗口,不是很灵活,为了CPU不影响ICMP报文,想找一款支持多核的Ping工具,但发现macOS不像Linux,没有Affinity和Taskset来给进程分配内核,最后找到一个用Go做的开源Ping软件,并支持多线程,但这个运行有些问题,需要排障;
此篇文章简单用实例总结Go的初体验,以及Go程序的排错方法,方便以后复习查阅。
机器环境
System: macOS Monterey 12.1
Arch: darwin/arm64
Go ver: 1.17.5
安装Go及调试环境
安装
安装很简单,直接去官网 https://go.dev/doc/install 选择相应的版本直接下载安装即可,细节不在此说明了。不过问题是国内网络环境不好,需要科学上网才可以(学习知识也需要科学上网,真的很尴尬 -_- );
安装后,可以通过下面命令来验证Go的版本:
xxx@Yongs-MacBook-Pro ~ % go version
go version go1.17.5 darwin/arm64
配置环境
从10.15.x开始,macOS使用zsh作为默认的shell,所以环境变量需要写到~/.zprofile中,而不是~/.bash_profile,看默认的shell是什么,可以用下面命令:
xxx@Yongs-MacBook-Pro ~ % echo $SHELL
/bin/zsh
- /bin/zsh => zsh => .zprofile
- /bin/bash => bash => .bash_profile
所以把Go的环境写到~/.zprofile中,如下:
xxx@Yongs-MacBook-Pro ~ % more .zprofile |grep GO
export GOPATH=/Users/xxx/Documents/go
建立Go的相关目录,其中file下存着Go的程序,src中存着各种module/库:
xxx@Yongs-MacBook-Pro go % tree -L 1
.
├── file
└── src
第一个Go程序
xxx@Yongs-MacBook-Pro first % more first.go
package main
import "fmt"
func main(){
fmt.Println("This is my first go program")
}
执行程序可以使用Go run,这个是先编译在执行,但执行完后自动删除编译文件:
xxx@Yongs-MacBook-Pro first % go run first.go
This is my first go program
xxx@Yongs-MacBook-Pro first % ls
first.go
beihe@Yongs-MacBook-Pro first % pwd
/Users/xxx/Documents/go/file/first
执行程序也可以用Go build,先编译,然后执行编译后的程序:
xxx@Yongs-MacBook-Pro first % go build first.go
xxx@Yongs-MacBook-Pro first % ls
total 3784
-rwxr-xr-x 1 beihe staff 1932642 Jan 7 13:34 first
-rw-r--r-- 1 beihe staff 92 Jan 7 12:16 first.go
xxx@Yongs-MacBook-Pro first % ./first
This is my first go program
第三方库文件加载
原有程序在这个github:https://github.com/feiyu563/nbping;把源文件copy到本地,然后编译,发现有下面错误:
xxx@Yongs-MacBook-Pro nbping % go build nbping.go
nbping.go:8:2: no required module provides package golang.org/x/net/icmp: go.mod file not found in current directory or any parent directory; see 'go help modules'
nbping.go:9:2: no required module provides package golang.org/x/net/ipv4: go.mod file not found in current directory or any parent directory; see 'go help modules'
xxx@Yongs-MacBook-Pro ping % more ping.go
package main
import (
"bufio"
"errors"
"flag"
"fmt"
"golang.org/x/net/icmp"
"golang.org/x/net/ipv4"
"io/ioutil"
"math/rand"
"net"
"os"
"strings"
"time"
)
......
Go的import跟Python基本一样,唯一区别的是在引用第三方库文件时,使用地址的方式,比如上面的golang.org/x/net/icmp和golang.org/x/net/ipv4。Get这些库文件可以使用下面命令,但由于环境问题,需要用代理,常规的基于web的科学上网是不行的,即使把GOPROXY改成.cn的也不行:
xxx@Yongs-MacBook-Pro src % go env -w GOPROXY=https://goproxy.cn,direct
xxx@Yongs-MacBook-Pro src % go env -w GO111MODULE=auto
xxx@Yongs-MacBook-Pro src % go env |grep -E "GO111|cn"
GO111MODULE="auto"
GOPROXY="https://goproxy.cn,direct"
xxx@Yongs-MacBook-Pro src % go get -u golang.org/x/net
package golang.org/x/net: unrecognized import path "golang.org/x/net": https fetch: Get "https://golang.org/x/net?go-get=1": dial tcp 142.251.43.17:443: i/o timeout
有没有不用代理解决此问题的方法?经过查找,可以直接从github(https://github.com/golang/)下载库文件到src目录下,这个github地址就是go做的一个镜像,所以可以无脑用:
xxx@Yongs-MacBook-Pro go % mkdir -p $GOPATH/src/golang.org/x
xxx@Yongs-MacBook-Pro go % cd $GOPATH/src/golang.org/x
xxx@Yongs-MacBook-Pro x % git clone https://github.com/golang/net.git
Cloning into 'net'...
remote: Enumerating objects: 10910, done.
remote: Counting objects: 100% (8/8), done.
remote: Compressing objects: 100% (7/7), done.
remote: Total 10910 (delta 1), reused 6 (delta 1), pack-reused 10902
Receiving objects: 100% (10910/10910), 8.88 MiB | 808.00 KiB/s, done.
Resolving deltas: 100% (7781/7781), done.
xxx@Yongs-MacBook-Pro x % git clone https://github.com/golang/sys.git
Cloning into 'sys'...
remote: Enumerating objects: 12852, done.
remote: Counting objects: 100% (1322/1322), done.
remote: Compressing objects: 100% (462/462), done.
remote: Total 12852 (delta 998), reused 1044 (delta 858), pack-reused 11530
Receiving objects: 100% (12852/12852), 11.02 MiB | 1.74 MiB/s, done.
Resolving deltas: 100% (10922/10922), done.
xxx@Yongs-MacBook-Pro ping %
xxx@Yongs-MacBook-Pro ping % go build ping.go
xxx@Yongs-MacBook-Pro go % tree -L 4
.
├── file
│ ├── first
│ │ ├── first
│ │ └── first.go
│ └── ping
│ ├── ping
│ └── ping.go
└── src
└── golang.org
└── x
├── net
└── sys
8 directories, 4 files
202406-更新:交叉编译
我在MBP上写了2个程序,编译后转到linux发现执行不了,想了下应该是MBP是ARM架构,编译默认是ARM架构,所以Linux无法执行,那么需要交叉编译,很简单,一条命令即可搞定,秒出:
Frank@Franks-MacBook-Pro all2all % ls -l
total 19504
-rwxr-xr-x 1 Frank staff 2472610 Jun 9 22:12 client
-rw-r--r--@ 1 Frank staff 4776 Jun 9 21:56 client.go
-rw-r--r--@ 1 Frank staff 372172 Jun 9 22:09 client_output.txt
-rw-r--r--@ 1 Frank staff 767 Jun 9 20:22 credentials.txt
-rwxr-xr-x 1 Frank staff 2472610 Jun 9 22:12 server
-rw-r--r--@ 1 Frank staff 4797 Jun 9 21:58 server.go
-rw-r--r--@ 1 Frank staff 1416510 Jun 9 22:06 server_output.txt
-rw-r--r-- 1 Frank staff 6448 Jun 9 22:21 temp_ports.txt
Frank@Franks-MacBook-Pro all2all % CGO_ENABLED=0 GOARCH=amd64 GOOS=linux go build -o client_x86 client.go
Frank@Franks-MacBook-Pro all2all % CGO_ENABLED=0 GOARCH=amd64 GOOS=linux go build -o server_x86 server.go
Frank@Franks-MacBook-Pro all2all % ls -l
total 24456
-rwxr-xr-x 1 Frank staff 2472610 Jun 9 22:12 client
-rw-r--r--@ 1 Frank staff 4776 Jun 9 21:56 client.go
-rw-r--r--@ 1 Frank staff 372172 Jun 9 22:09 client_output.txt
-rwxr-xr-x 1 Frank staff 2534697 Jun 9 22:28 client_x86
-rw-r--r--@ 1 Frank staff 767 Jun 9 20:22 credentials.txt
-rwxr-xr-x 1 Frank staff 2472610 Jun 9 22:12 server
-rw-r--r--@ 1 Frank staff 4797 Jun 9 21:58 server.go
-rw-r--r--@ 1 Frank staff 1416510 Jun 9 22:06 server_output.txt
-rwxr-xr-x 1 Frank staff 2534545 Jun 9 22:28 server_x86
-rw-r--r-- 1 Frank staff 6448 Jun 9 22:21 temp_ports.txt
下面是linux平台上:
c@tme97:~/frank$ chmod +x server_x86
c@tme97:~/frank$ chmod +x client_x86
c@tme97:~/frank$ sudo apt-get install sshpass
clounix@tme97:~/frank$ ./server_x86
2024/06/09 14:38:14 2024-06-09 14:38:14.005981 - Connecting to 10.22.1.69:22
2024/06/09 14:38:14 2024-06-09 14:38:14.005963 - Connecting to 10.22.1.69:22
2024/06/09 14:38:14 2024-06-09 14:38:14.012501 - Connecting to 10.22.1.69:22
2024/06/09 14:38:14 2024-06-09 14:38:14.025972 - Connecting to 10.22.1.8:22
Go程序排障
等待更新……