前篇的文章是以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.合适的开发语言