vscode配置golang开发环境

一、安装 VSCode 和 Golang

二、在 go module 模式下加载工具包

mkdir test
cd test
go mod init test

三、配置代理

// set GOPROXY=https://proxy.golang.org
set GOPROXY=https://mirrors.aliyun.com/goproxy/

// GO 1.13+
go env -w GOPROXY=https://mirrors.aliyun.com/goproxy,direct
go env -w GOSUMDB=sum.golang.google.cn

四、下载依赖包

go get github.com/stamblerre/gocode
rename %GOPATH%/gocode.exe %GOPATH%/gocode-gomod.exe

go get github.com/mdempsky/gocode
go get github.com/uudashr/gopkgs/cmd/gopkgs
go get github.com/ramya-rao-a/go-outline
go get github.com/acroca/go-symbols
go get golang.org/x/tools/cmd/guru
go get golang.org/x/tools/cmd/gorename
go get github.com/go-delve/delve/cmd/dlv
go get github.com/rogpeppe/godef
go get golang.org/x/tools/cmd/goimports
go get golang.org/x/lint/golint
go get golang.org/x/tools/gopls

开发环境镜像设置

一、阿里系镜像

# Composer
composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/

# npm
npm config set registry https://registry.npm.taobao.org --global
npm config set disturl https://npm.taobao.org/dist --global

# CentOS
curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo

# epel
curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo

# Pypi
echo "[global]
index-url = https://mirrors.aliyun.com/pypi/simple/

[install]
trusted-host=mirrors.aliyun.com" > ~/.pip/pip.conf

二、其他镜像

# GoProxy Win
# set GOPROXY=https://proxy.golang.org
setx GOPROXY=https://mirrors.aliyun.com/goproxy/

# GoProxy Linux
# export GOPROXY=https://proxy.golang.org
export GOPROXY=https://mirrors.aliyun.com/goproxy/

Go Module 开发环境配置

一、初始化项目

mkdir go-app
cd go-app
go mod init app

二、设置第三方依赖包

go get github.com/go-sql-driver/mysql@v1.4.1
go get github.com/gin-gonic/gin@v1.5.0
go get github.com/gomodule/redigo/redis@v1.7.0

三、开始编码

package main

import (
	"database/sql"
	"log"

	"github.com/gin-gonic/gin"
	_ "github.com/go-sql-driver/mysql"
)

var db *sql.DB

func main() {
	databaseInit()
	defer db.Close()
	gin.SetMode(gin.ReleaseMode)
	r := gin.Default()
	r.GET("/", IndexAction)
	r.GET("/user/:name", UserAction)
	r.Run()
}

func databaseInit() {
	var err error
	db, err = sql.Open("mysql", "root:123456@tcp(127.0.0.1:3306)/wordpress")
	if err != nil {
		log.Fatalln(err)
	}
	db.SetMaxIdleConns(500)
	db.SetMaxOpenConns(500)
	err = db.Ping()
	if err != nil {
		log.Fatalln(err)
	}
}

func IndexAction(c *gin.Context) {
	c.JSON(200, gin.H{"message": "index"})
}

func UserAction(c *gin.Context) {
	var ID int
	err := db.QueryRow("SELECT ID FROM wp_users WHERE user_login = ?", c.Param("name")).Scan(&ID)
	if err == nil {
		c.String(200, "Hello %d", ID)
	} else {
		c.String(200, "Hello nobody")
	}
}

四、生成本地依赖

go mod vendor

五、运行

go run -mod=vendor main.go

扫描局域网内80端口

package main

import (
	"fmt"
	"net"
	"strconv"
)

func main() {

	count := 254
	run := make([]chan int, count)

	for index := 0; index < count; index++ {
		run[index] = make(chan int)
	}

	for index := 0; index < count; index++ {
		go func(i int) {
			ip := "192.168.1." + strconv.Itoa(i+1)
			p := scanPort(ip)
			fmt.Println(ip, "\t", p)
			run[i] <- i
		}(index)
	}

	for index := 0; index < count; index++ {
		<-run[index]
	}

}

func scanPort(ip string) bool {
	conn, err := net.Dial("tcp", ip+":80")
	if err != nil {
		return false
	}
	defer conn.Close()
	return true
}

Go构建DNS请求包

1. DNS请求报文头

[]byte{0x01, 0b100000000, 1, 0, 0, 0}

2. 查询的域名 QNAME

func parseDomain(domain string) []byte {
	var b = []byte{}
	for _, s := range strings.Split(domain, ".") {
		b = append(b, byte(len(s)))
		b = append(b, []byte(s)...)
	}
	b = append(b, byte(0x00))
	return b
}

3. 报文头尾部

[]byte{1, 1}

阿里云OSS表单上传签名

/**
 *  阿里云 OSS 密钥
 */
define('AccessKeyId', 'ID');
define('AccessKeySecret', 'SS');
define('OssHost', 'https://bucket.oss-cn-beijing.aliyuncs.com');
define('UploadPrefix', 'files/');

function ossUploadSign($expire = 60) {
    $sign = [];
    $sign['accessid'] = AccessKeyId;
    $sign['host'] = OssHost;
    $sign['expire'] = time() + $expire;
    $sign['policy'] = base64_encode(json_encode(['expiration' => date('Y-m-d\TH:i:s\Z', $sign['expire']), 'conditions' => [['content-length-range', 0, 100 * 1024 * 1024], ['starts-with', '$key', UploadPrefix]]]));
    $sign['signature'] = base64_encode(hash_hmac('sha1', $sign['policy'], AccessKeySecret, true));
    $sign['dir'] = UploadPrefix;
    return json_encode($sign);
}

echo ossUploadSign();

FRP服务端和客户端配置

一、服务端配置

# frps.ini
[common]
bind_port = 7000
token = 12345678

二、客户端配置

1. 客户端提供服务方

# frpc-01.ini
[common]
server_addr = 1.2.3.4
server_port = 7000
token = 12345678

[service_name]
type = stcp
sk = abcdefg
local_ip = 127.0.0.1
local_port = 22
use_encryption = false
use_compression = true

2. 客户端连接方

# frpc-02.ini
[common]
server_addr = 1.2.3.4
server_port = 7000
token = 12345678

[client_name]
role = visitor
type = stcp
server_name = service_name
sk = abcdefg
bind_addr = 127.0.0.1
bind_port = 2201
use_encryption = false
use_compression = true

Go 开发环境配置

以下方式已不建议使用,使用 Go Module 配置的方式

一、安装 govendor 工具

go get -u github.com/kardianos/govendor

二、创建工程

cd $GOPATH/src
mkdir demo
cd demo
govendor init

三、安装依赖

govendor fetch github.com/go-sql-driver/mysql@=v1.4.1
govendor fetch github.com/gin-gonic/gin@=v1.3.0
govendor fetch github.com/gomodule/redigo/redis@=v1.7.0

四、开发

package main

import (
	"database/sql"
	"log"

	"github.com/gin-gonic/gin"
	_ "github.com/go-sql-driver/mysql"
)

var Database *sql.DB

func main() {
	DatabaseInit()
	defer Database.Close()
	gin.SetMode(gin.ReleaseMode)
	r := gin.Default()
	r.GET("/", IndexAction)
	r.GET("/user/:name", UserAction)
	r.Run()
}

func DatabaseInit() {
	var err error
	Database, err = sql.Open("mysql", "root:123456@tcp(127.0.0.1:3306)/wordpress")
	if err != nil {
		log.Fatalln(err)
	}
	Database.SetMaxIdleConns(500)
	Database.SetMaxOpenConns(500)
	err = Database.Ping()
	if err != nil {
		log.Fatalln(err)
	}
}

func IndexAction(c *gin.Context) {
	c.JSON(200, gin.H{"message": "index"})
}

func UserAction(c *gin.Context) {
	var ID int
	err := Database.QueryRow("SELECT ID FROM wp_users WHERE user_login = ?", c.Param("name")).Scan(&ID)
	if err == nil {
		c.String(200, "Hello %d", ID)
	} else {
		c.String(200, "Hello nobody")
	}
}

五、gin-app

gin-app-0.1

golang发送阿里云短信

package main

import (
	"crypto/hmac"
	"crypto/sha1"
	"encoding/base64"
	"fmt"
	"io/ioutil"
	"math/rand"
	"net/http"
	"net/url"
	"sort"
	"strconv"
	"strings"
	"time"
)

const AccessKeyID = "0000"
const AccessKeySecret = "1111"
const TemplateCode = "SMS_2222"
const SignName = "发送测试"

func UrlEncode(in string) string {
	r := strings.NewReplacer("+", "%20", "*", "%2A", "%7E", "~")
	return r.Replace(url.QueryEscape(in))
}

func Sign(stringToSign string) string {
	h := hmac.New(sha1.New, []byte(fmt.Sprintf("%s&", AccessKeySecret)))
	h.Write([]byte(stringToSign))
	return UrlEncode(base64.StdEncoding.EncodeToString(h.Sum(nil)))
}

func Keys(data map[string]string) []string {
	var keys []string
	for k := range data {
		keys = append(keys, k)
	}
	sort.Strings(keys)
	return keys
}

func SortedString(data map[string]string) string {
	var sortQueryString string
	for _, v := range Keys(data) {
		sortQueryString = fmt.Sprintf("%s&%s=%s", sortQueryString, v, UrlEncode(data[v]))
	}
	return sortQueryString
}

func AliyunSendSMS(PhoneNumber string, code string) string {

	rand.Seed(time.Now().UnixNano())

	data := map[string]string{
		"SignatureMethod":  "HMAC-SHA1",
		"SignatureNonce":   strconv.FormatFloat(rand.Float64(), 'f', 6, 64),
		"AccessKeyId":      AccessKeyID,
		"SignatureVersion": "1.0",
		"Timestamp":        time.Now().UTC().Format("2006-01-02T15:04:05Z"),
		"Format":           "JSON",

		"RegionId":      "cn-hangzhou",
		"Action":        "SendSms",
		"Version":       "2017-05-25",
		"PhoneNumbers":  PhoneNumber,
		"SignName":      SignName,
		"TemplateCode":  TemplateCode,
		"TemplateParam": `{"code":"` + code + `"}`,
	}

	sortQueryString := SortedString(data)
	stringToSign := "GET&%2F&" + UrlEncode(sortQueryString[1:])
	url := fmt.Sprintf("https://dysmsapi.aliyuncs.com/?Signature=%s%s", Sign(stringToSign), sortQueryString)

	r, err := http.Get(url)
	if err != nil {
		return ""
	}
	defer r.Body.Close()

	b, err := ioutil.ReadAll(r.Body)
	if err != nil {
		return ""
	}

	return string(b)
}

func main() {
	html := AliyunSendSMS("18611112222", "123456")
	fmt.Println(html)
}