前篇的文章是以Java语言为讲解的,现在我们翻译为Go语言来进行简单的讲解,在线运行代码可以用:https://play.golang.org/
1. Id生成器最初版是这样的
package main
import (
"fmt"
"math/rand"
"os"
"strings"
"time"
)
//最初代码
func GetId() string {
id := ""
hostName, _ := os.Hostname()
tokens := strings.Split(hostName, ".")
if len(tokens) > 0 {
hostName = tokens[len(tokens)-1]
}
var randomChars = make([]string, 8)
for count := 0; count < 8; {
randomAscii := rand.Intn(122)
if randomAscii >= 48 && randomAscii <= 57 {
randomChars[count] = string(rune(randomAscii))
count++
} else if randomAscii >= 65 && randomAscii <= 90 {
randomChars[count] = string(rune(randomAscii))
count++
} else if randomAscii >= 97 && randomAscii <= 122 {
randomChars[count] = string(rune(randomAscii))
count++
}
}
id = fmt.Sprintf("%s-%d-%s", hostName, time.Now().UnixNano()/1e6, strings.Join(randomChars, ""))
return id
}
func main() {
for i := 1; i <= 5; i++ {
fmt.Println(GetId())
}
}
程序执行结果如下:
c:/go/bin/go.exe build [E:/source/golang/src/newtest] 成功: 进程退出代码 0. E:/source/golang/src/newtest/newtest.exe [E:/source/golang/src/newtest] zhangsujie-d1-1611891447604-mKrxC4h5 zhangsujie-d1-1611891447605-t8FeaooS zhangsujie-d1-1611891447605-MQEyOEci zhangsujie-d1-1611891447605-DydDsBOl zhangsujie-d1-1611891447605-VvxLQDVQ 成功: 进程退出代码 0.
2. 第一版优化(拆分并封装成类)
package main
import (
"fmt"
"math/rand"
"os"
"strings"
"time"
)
//第一版优化
type RandomIdGenerator1 struct {
}
func (ra RandomIdGenerator1) Generate() string {
substrOfHostName := ra.getLastfieldOfHostName()
currentTimeMillis := time.Now().UnixNano() / 1e6
randomString := ra.generateRandomAlphameric(8)
id := fmt.Sprintf("%s-%d-%s", substrOfHostName, currentTimeMillis, randomString)
return id
}
func (ra RandomIdGenerator1) getLastfieldOfHostName() string {
substrOfHostName := ""
hostName, _ := os.Hostname()
tokens := strings.Split(hostName, ".")
if len(tokens) > 0 {
substrOfHostName = tokens[len(tokens)-1]
}
return substrOfHostName
}
func (ra RandomIdGenerator1) generateRandomAlphameric(length int) string {
randomChars := make([]string, length)
for count := 0; count < length; {
maxAscii := int('z')
randomAscii := rand.Intn(maxAscii)
isDigit := randomAscii >= int('0') && randomAscii <= int('9')
isUppercase := randomAscii >= int('A') && randomAscii <= int('Z')
isLowercase := randomAscii >= int('a') && randomAscii <= int('z')
if isDigit || isUppercase || isLowercase {
randomChars[count] = string(rune(randomAscii))
count++
}
}
return strings.Join(randomChars, "")
}
func main() {
rn1 := new(RandomIdGenerator1)
for i := 1; i <= 5; i++ {
fmt.Println(rn1.Generate())
}
}
程序执行结果如下:
c:/go/bin/go.exe build [E:/source/golang/src/newtest] 成功: 进程退出代码 0. E:/source/golang/src/newtest/newtest.exe [E:/source/golang/src/newtest] zhangsujie-d1-1611892006330-mKrxC4h5 zhangsujie-d1-1611892006330-t8FeaooS zhangsujie-d1-1611892006330-MQEyOEci zhangsujie-d1-1611892006330-DydDsBOl zhangsujie-d1-1611892006330-VvxLQDVQ 成功: 进程退出代码 0.
3. 第二版优化(优化随机字符方法)
package main
import (
"fmt"
"math/rand"
"os"
"strings"
"time"
)
//第二版优化
type RandomIdGenerator2 struct {
}
func (ra RandomIdGenerator2) Generate() string {
substrOfHostName := ra.getLastfieldOfHostName()
currentTimeMillis := time.Now().UnixNano() / 1e6
randomString := ra.generateRandomAlphameric(8)
id := fmt.Sprintf("%s-%d-%s", substrOfHostName, currentTimeMillis, randomString)
return id
}
func (ra RandomIdGenerator2) getLastfieldOfHostName() string {
substrOfHostName := ""
hostName, _ := os.Hostname()
tokens := strings.Split(hostName, ".")
if len(tokens) > 0 {
substrOfHostName = tokens[len(tokens)-1]
}
return substrOfHostName
}
func (ra RandomIdGenerator2) generateRandomAlphameric(length int) string {
letterRunes := []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
b := make([]rune, length)
for i := range b {
b[i] = letterRunes[rand.Intn(len(letterRunes))]
}
return string(b)
}
func main() {
rn2 := new(RandomIdGenerator2)
for i := 1; i <= 5; i++ {
fmt.Println(rn2.Generate())
}
}
程序执行结果如下:
c:/go/bin/go.exe build [E:/source/golang/src/newtest] 成功: 进程退出代码 0. E:/source/golang/src/newtest/newtest.exe [E:/source/golang/src/newtest] zhangsujie-d1-1611903141521-BpLnfgDs zhangsujie-d1-1611903141522-c2WD8F2q zhangsujie-d1-1611903141522-NfHK5a84 zhangsujie-d1-1611903141522-jjJkwzDk zhangsujie-d1-1611903141522-h9h2fhfU 成功: 进程退出代码 0.
4. 第三版优化(优化获取主机名称)
package main
import (
"fmt"
"math/rand"
"os"
"strings"
"time"
)
//第三版优化
func getHostName() string {
substrOfHostName := ""
hostName, _ := os.Hostname()
tokens := strings.Split(hostName, ".")
if len(tokens) > 0 {
substrOfHostName = tokens[len(tokens)-1]
}
return substrOfHostName
}
var hostName = getHostName()
type RandomIdGenerator3 struct {
}
func (ra RandomIdGenerator3) Generate() string {
currentTimeMillis := time.Now().UnixNano() / 1e6
randomString := ra.generateRandomAlphameric(8)
id := fmt.Sprintf("%s-%d-%s", hostName, currentTimeMillis, randomString)
return id
}
func (ra RandomIdGenerator3) generateRandomAlphameric(length int) string {
letterRunes := []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
b := make([]rune, length)
for i := range b {
b[i] = letterRunes[rand.Intn(len(letterRunes))]
}
return string(b)
}
func main() {
rn3 := new(RandomIdGenerator3)
for i := 1; i <= 5; i++ {
fmt.Println(rn3.Generate())
}
}
程序执行结果如下:
c:/go/bin/go.exe build [E:/source/golang/src/newtest] 成功: 进程退出代码 0. E:/source/golang/src/newtest/newtest.exe [E:/source/golang/src/newtest] zhangsujie-d1-1611903748157-BpLnfgDs zhangsujie-d1-1611903748157-c2WD8F2q zhangsujie-d1-1611903748157-NfHK5a84 zhangsujie-d1-1611903748157-jjJkwzDk zhangsujie-d1-1611903748157-h9h2fhfU 成功: 进程退出代码 0.
5.这样写行不行?
package main
import (
"fmt"
"math/rand"
"time"
"github.com/google/uuid"
)
func main() {
//以下这样可不可以??
fmt.Println(fmt.Sprintf("%d-%d", time.Now().UnixNano(), rand.Intn(89999999)+10000000))
fmt.Println(uuid.New().String())
}
程序执行结果如下:
c:/go/bin/go.exe build [E:/source/golang/src/newtest] 成功: 进程退出代码 0. E:/source/golang/src/newtest/newtest.exe [E:/source/golang/src/newtest] 1611904029112094900-48498095 082f14ba-cdec-49ce-8c5f-d9194d429425 成功: 进程退出代码 0.
总的来说,技术的实现是为业务来服务的,如果只是为了生成一个日志id方便上下游来排查问题,直接用一个简单的方法也没有问题。
代码质量问题,可以参考一个工具。
项目地址:https://github.com/360EntSecGroup-Skylar/goreporter
演示示例:http://wgliang.github.io/pages/goreporter-report.html

一个项目要考虑的问题有那些?
1:源代码管理
2:文档管理
3:开发环境及运行环境
4:上线流程及稳定性
5:监控及报警
6.合适的开发语言