GolangUtils
- 1: goroutine
- 2: Map
- 3: 表单验证
- 4: 结构体
- 5: 进制转换
- 6: 日期时间函数
- 7: 数据类型转换
- 8: 数学函数
- 9: 文件目录操作函数
- 10: 系统变量初始化
- 11: 序列化
- 12: 整型
- 13: 字符串函数
- 14: 字节数组操作([]byte)
1 - goroutine
获取goroutineID
func goID() uint64 {
b := make([]byte, 64)
b = b[:runtime.Stack(b, false)]
b = bytes.TrimPrefix(b, []byte("goroutine "))
b = b[:bytes.IndexByte(b, ' ')]
n, _ := strconv.ParseUint(string(b), 10, 64)
return n
}
2 - Map
初始化
// 先声明map
var m1 map[string]string
// 再使用make函数创建一个非nil的map,nil map不能赋值
m1 = make(map[string]string)
// 最后给已声明的map赋值
m1["a"] = "aa"
m1["b"] = "bb"
// 直接创建
m2 := make(map[string]string)
// 然后赋值
m2["a"] = "aa"
m2["b"] = "bb"
// 初始化 + 赋值一体化
m3 := map[string]string{
"a": "aa",
"b": "bb",
}
判断key是否存在
if v, ok := m1["a"]; ok {
fmt.Println(v)
} else {
fmt.Println("Key Not Found")
}
遍历map
for k, v := range m1 {
fmt.Println(k, v)
}
删除一个元素
scene := make(map[string]int)
// 准备map数据
scene["route"] = 66
scene["brazil"] = 4
scene["china"] = 960
delete(scene, "brazil")
for k, v := range scene {
fmt.Println(k, v)
}
//route 66
//china 960
安全的Map
1. map+锁
type SafeMap struct {
Data map[string]interface{}
Lock sync.RWMutex
}
func (this *SafeMap) Get(k string) interface{} {
this.Lock.RLock()
defer this.Lock.RUnlock()
if v, exit := this.Data[k]; exit {
return v
}
return nil
}
func (this *SafeMap) Set(k string, v interface{}) {
this.Lock.Lock()
defer this.Lock.Unlock()
if this.Data == nil {
this.Data = make(map[string]interface{})
}
this.Data[k] = v
}
2. sync.map
var test sync.Map
//设置元素
func set (k,v interface{}){
test.Store(k,v)
}
//获得元素
func get (k interface{}) interface{}{
tem ,exit := test.Load(k)
if exit {
return tem
}
return nil
}
//传入一个 函数 ,sync.map 会内部迭代 ,运行这个函数
func ranggfunc (funcs func(key, value interface{}) bool) {
test.Range(funcs)
}
//删除元素
func del(key interface{}){
test.Delete(key)
}
4 - 结构体
判断变量是否==空结构体
if reflect.DeepEqual(deviceModel, models.DeviceModel{}) {
//code
}
结构提转map
//使用反射转换的效率要高于 struct->json->map
//传变量
func Struct2Map(obj interface{}) map[string]interface{} {
t := reflect.TypeOf(obj)
v := reflect.ValueOf(obj)
var data = make(map[string]interface{})
for i := 0; i < t.NumField(); i++ {
data[t.Field(i).Name] = v.Field(i).Interface()
}
return data
}
//传指针,如果一定要声明称指针( obj := new(Test)或obj := &Test{} )时,Struct2Map方法中需要将取出指针的内容然后继续操作,因为指针是没有Field()方法的。
func Struct2Map(obj interface{}) map[string]interface{} {
obj_v := reflect.ValueOf(obj)
v := obj_v.Elem()
typeOfType := v.Type()
var data = make(map[string]interface{})
for i := 0; i < v.NumField(); i++ {
field := v.Field(i)
data[typeOfType.Field(i).Name] = field.Interface()
}
return data
}
// Clone deep-copies a to b
func Clone(a, b interface{}) {
buff := new(bytes.Buffer)
enc := gob.NewEncoder(buff)
dec := gob.NewDecoder(buff)
enc.Encode(a)
dec.Decode(b)
}
func main() {
a1 := A{
AA: "jilao",
BB: 1,
}
var a2 A
Clone(a1, a2)
a2.AA = "lakjg;odfig"
fmt.Println(a1.AA)
fmt.Println(a2.AA)
}
5 - 进制转换
import (
"fmt"
"log"
"math"
"strconv"
"strings"
)
// Decimal to binary 十进制转二进制
func DecBin(n int64) string {
if n < 0 {
log.Println("Decimal to binary error: the argument must be greater than zero.")
return ""
}
if n == 0 {
return "0"
}
s := ""
for q := n; q > 0; q = q / 2 {
m := q % 2
s = fmt.Sprintf("%v%v", m, s)
}
return s
}
// Decimal to octal 十进制转八进制
func DecOct(d int64) int64 {
if d == 0 {
return 0
}
if d < 0 {
log.Println("Decimal to octal error: the argument must be greater than zero.")
return -1
}
s := ""
for q := d; q > 0; q = q / 8 {
m := q % 8
s = fmt.Sprintf("%v%v", m, s)
}
n, err := strconv.Atoi(s)
if err != nil {
log.Println("Decimal to octal error:", err.Error())
return -1
}
return int64(n)
}
// Decimal to hexadecimal 十进制转16进制
func DecHex(n int64) string {
if n < 0 {
log.Println("Decimal to hexadecimal error: the argument must be greater than zero.")
return ""
}
if n == 0 {
return "0"
}
hex := map[int64]int64{10: 65, 11: 66, 12: 67, 13: 68, 14: 69, 15: 70}
s := ""
for q := n; q > 0; q = q / 16 {
m := q % 16
if m > 9 && m < 16 {
m = hex[m]
s = fmt.Sprintf("%v%v", string(m), s)
continue
}
s = fmt.Sprintf("%v%v", m, s)
}
return s
}
// Binary to decimal 二进制转十进制
func BinDec(b string) (n int64) {
s := strings.Split(b, "")
l := len(s)
i := 0
d := float64(0)
for i = 0; i < l; i++ {
f, err := strconv.ParseFloat(s[i], 10)
if err != nil {
log.Println("Binary to decimal error:", err.Error())
return -1
}
d += f * math.Pow(2, float64(l-i-1))
}
return int64(d)
}
// Octal to decimal 八进制转十进制
func OctDec(o int64) (n int64) {
s := strings.Split(strconv.Itoa(int(o)), "")
l := len(s)
i := 0
d := float64(0)
for i = 0; i < l; i++ {
f, err := strconv.ParseFloat(s[i], 10)
if err != nil {
log.Println("Octal to decimal error:", err.Error())
return -1
}
d += f * math.Pow(8, float64(l-i-1))
}
return int64(d)
}
// Hexadecimal to decimal 十六进制转十进制
func HexDec(h string) (n int64) {
s := strings.Split(strings.ToUpper(h), "")
l := len(s)
i := 0
d := float64(0)
hex := map[string]string{"A": "10", "B": "11", "C": "12", "D": "13", "E": "14", "F": "15"}
for i = 0; i < l; i++ {
c := s[i]
if v, ok := hex[c]; ok {
c = v
}
f, err := strconv.ParseFloat(c, 10)
if err != nil {
log.Println("Hexadecimal to decimal error:", err.Error())
return -1
}
d += f * math.Pow(16, float64(l-i-1))
}
return int64(d)
}
// Octal to binary 八进制转二进制
func OctBin(o int64) string {
d := OctDec(o)
if d == -1 {
return ""
}
return DecBin(d)
}
// Hexadecimal to binary 十六进制转二进制
func HexBin(h string) string {
d := HexDec(h)
if d == -1 {
return ""
}
return DecBin(d)
}
// Binary to octal 二进制转八进制
func BinOct(b string) int64 {
d := BinDec(b)
if d == -1 {
return -1
}
return DecOct(d)
}
// Binary to hexadecimal 二进制转十六进制
func BinHex(b string) string {
d := BinDec(b)
if d == -1 {
return ""
}
return DecHex(d)
}
一个硬核的16进制转10进制 看起来有点笨, 但是很有效
var b2m_map map[byte]uint64 = map[byte]uint64{
0x00: 0,
0x01: 1,
0x02: 2,
0x03: 3,
0x04: 4,
0x05: 5,
0x06: 6,
0x07: 7,
0x08: 8,
0x09: 9,
0x0A: 10,
0x0B: 11,
0x0C: 12,
0x0D: 13,
0x0E: 14,
0x0F: 15,
0x10: 16,
0x11: 17,
0x12: 18,
0x13: 19,
0x14: 20,
0x15: 21,
0x16: 22,
0x17: 23,
0x18: 24,
0x19: 25,
0x1A: 26,
0x1B: 27,
0x1C: 28,
0x1D: 29,
0x1E: 30,
0x1F: 31,
0x20: 32,
0x21: 33,
0x22: 34,
0x23: 35,
0x24: 36,
0x25: 37,
0x26: 38,
0x27: 39,
0x28: 40,
0x29: 41,
0x2A: 42,
0x2B: 43,
0x2C: 44,
0x2D: 45,
0x2E: 46,
0x2F: 47,
0x30: 48,
0x31: 49,
0x32: 50,
0x33: 51,
0x34: 52,
0x35: 53,
0x36: 54,
0x37: 55,
0x38: 56,
0x39: 57,
0x3A: 58,
0x3B: 59,
0x3C: 60,
0x3D: 61,
0x3E: 62,
0x3F: 63,
0x40: 64,
0x41: 65,
0x42: 66,
0x43: 67,
0x44: 68,
0x45: 69,
0x46: 70,
0x47: 71,
0x48: 72,
0x49: 73,
0x4A: 74,
0x4B: 75,
0x4C: 76,
0x4D: 77,
0x4E: 78,
0x4F: 79,
0x50: 80,
0x51: 81,
0x52: 82,
0x53: 83,
0x54: 84,
0x55: 85,
0x56: 86,
0x57: 87,
0x58: 88,
0x59: 89,
0x5A: 90,
0x5B: 91,
0x5C: 92,
0x5D: 93,
0x5E: 94,
0x5F: 95,
0x60: 96,
0x61: 97,
0x62: 98,
0x63: 99,
0x64: 100,
0x65: 101,
0x66: 102,
0x67: 103,
0x68: 104,
0x69: 105,
0x6A: 106,
0x6B: 107,
0x6C: 108,
0x6D: 109,
0x6E: 110,
0x6F: 111,
0x70: 112,
0x71: 113,
0x72: 114,
0x73: 115,
0x74: 116,
0x75: 117,
0x76: 118,
0x77: 119,
0x78: 120,
0x79: 121,
0x7A: 122,
0x7B: 123,
0x7C: 124,
0x7D: 125,
0x7E: 126,
0x7F: 127,
0x80: 128,
0x81: 129,
0x82: 130,
0x83: 131,
0x84: 132,
0x85: 133,
0x86: 134,
0x87: 135,
0x88: 136,
0x89: 137,
0x8A: 138,
0x8B: 139,
0x8C: 140,
0x8D: 141,
0x8E: 142,
0x8F: 143,
0x90: 144,
0x91: 145,
0x92: 146,
0x93: 147,
0x94: 148,
0x95: 149,
0x96: 150,
0x97: 151,
0x98: 152,
0x99: 153,
0x9A: 154,
0x9B: 155,
0x9C: 156,
0x9D: 157,
0x9E: 158,
0x9F: 159,
0xA0: 160,
0xA1: 161,
0xA2: 162,
0xA3: 163,
0xA4: 164,
0xA5: 165,
0xA6: 166,
0xA7: 167,
0xA8: 168,
0xA9: 169,
0xAA: 170,
0xAB: 171,
0xAC: 172,
0xAD: 173,
0xAE: 174,
0xAF: 175,
0xB0: 176,
0xB1: 177,
0xB2: 178,
0xB3: 179,
0xB4: 180,
0xB5: 181,
0xB6: 182,
0xB7: 183,
0xB8: 184,
0xB9: 185,
0xBA: 186,
0xBB: 187,
0xBC: 188,
0xBD: 189,
0xBE: 190,
0xBF: 191,
0xC0: 192,
0xC1: 193,
0xC2: 194,
0xC3: 195,
0xC4: 196,
0xC5: 197,
0xC6: 198,
0xC7: 199,
0xC8: 200,
0xC9: 201,
0xCA: 202,
0xCB: 203,
0xCC: 204,
0xCD: 205,
0xCE: 206,
0xCF: 207,
0xD0: 208,
0xD1: 209,
0xD2: 210,
0xD3: 211,
0xD4: 212,
0xD5: 213,
0xD6: 214,
0xD7: 215,
0xD8: 216,
0xD9: 217,
0xDA: 218,
0xDB: 219,
0xDC: 220,
0xDD: 221,
0xDE: 222,
0xDF: 223,
0xE0: 224,
0xE1: 225,
0xE2: 226,
0xE3: 227,
0xE4: 228,
0xE5: 229,
0xE6: 230,
0xE7: 231,
0xE8: 232,
0xE9: 233,
0xEA: 234,
0xEB: 235,
0xEC: 236,
0xED: 237,
0xEE: 238,
0xEF: 239,
0xF0: 240,
0xF1: 241,
0xF2: 242,
0xF3: 243,
0xF4: 244,
0xF5: 245,
0xF6: 246,
0xF7: 247,
0xF8: 248,
0xF9: 249,
0xFA: 250,
0xFB: 251,
0xFC: 252,
0xFD: 253,
0xFE: 254,
0xFF: 255,
}
func hex2int(hexB *[]byte) uint64 {
var retInt uint64
hexLen := len(*hexB)
for k, v := range *hexB {
retInt += b2m_map[v] * exponent(16, uint64(2*(hexLen-k-1)))
}
return retInt
}
6 - 日期时间函数
对2006-01-02 15:04:05 (go的诞生时间) 按照123456来记忆:01月02号 下午3点04分05秒 2006年
获得秒,毫秒,纳秒时间戳
fmt.Printf("时间戳(秒):%v;\n", time.Now().Unix())
fmt.Printf("时间戳(纳秒):%v;\n",time.Now().UnixNano())
fmt.Printf("时间戳(毫秒):%v;\n",time.Now().UnixNano() / 1e6)
fmt.Printf("时间戳(纳秒转换为秒):%v;\n",time.Now().UnixNano() / 1e9)
获取格式化的前 5秒,5分钟,5小时,5天,5个月,5年前的时间
对 分小时天月年 设置格式 Format(“2006-01-02 15:04:05”) —> Format(“2006-01-02 15:00:00”), 写成00就是把对应位置直接赋值成00
st,_ := time.ParseDuration("-5s")
fmt.Println("5秒前的时间:",time.Now().Add(st).Format("2006-01-02 15:04:05"))
fmt.Println("5秒前的时间:",time.Now().Add(time.Second*-5).Format("2006-01-02 15:04:05"))
st,_ = time.ParseDuration("-5m")
fmt.Println("5分前的时间:",time.Now().Add(st).Format("2006-01-02 15:04:05"))
fmt.Println("5分前的时间:",time.Now().Add(time.Minute*-5).Format("2006-01-02 15:04:05"))
st,_ = time.ParseDuration("-5h")
fmt.Println("5小时前的时间:",time.Now().Add(st).Format("2006-01-02 15:04:05"))
fmt.Println("5小时前的时间:",time.Now().Add(time.Hour*-5).Format("2006-01-02 15:04:05"))
fmt.Println("5天前的时间:",time.Now().AddDate(0, 0, -5).Format("2006-01-02 15:04:05"))
fmt.Println("5月前的时间:",time.Now().AddDate(0, -5, 0).Format("2006-01-02 15:04:05"))
fmt.Println("5年前的时间:",time.Now().AddDate(-5, 0, 0).Format("2006-01-02 15:04:05"))
外部传入字符串时间戳输出
package main
import (
"log"
"time"
)
func main() {
t := int64(1595581744) //外部传入的时间戳(秒为单位),必须为int64类型, time.Unix(t, 0)必须是到秒的时间戳
t1 := "2019-01-08 13:50:30" //外部传入的时间字符串
//时间转换的模板,golang里面只能是 "2006-01-02 15:04:05" (go的诞生时间)
timeTemplate1 := "2006-01-02 15:04:05" //常规类型
timeTemplate2 := "2006/01/02 15:04:05" //其他类型
timeTemplate3 := "2006-01-02" //其他类型
timeTemplate4 := "15:04:05" //其他类型
// ======= 将时间戳格式化为日期字符串 =======
log.Println(time.Unix(t, 0).Format(timeTemplate1)) //输出:2019-01-08 13:50:30
log.Println(time.Unix(t, 0).Format(timeTemplate2)) //输出:2019/01/08 13:50:30
log.Println(time.Unix(t, 0).Format(timeTemplate3)) //输出:2019-01-08
log.Println(time.Unix(t, 0).Format(timeTemplate4)) //输出:13:50:30
// ======= 将时间字符串转换为时间戳 =======
stamp, _ := time.ParseInLocation(timeTemplate1, t1, time.Local) //使用parseInLocation将字符串格式化返回本地时区时间
log.Println(stamp.Unix()) //输出:1546926630
}
7 - 数据类型转换
string to other = 字符串转其他
string -> int
i1, err := strconv.Atoi("1")
string -> int64
i64, err := strconv.ParseInt("2", 10, 64)
hexstring -> []byte 16进制字符串转(16进制代表的)byte数组
hex_str := "4161"
hex_data, _ := hex.DecodeString(hex_str)
fmt.Println(string(hexData))//Aa
8 - 数学函数
向上取整math.Ceil() 向下取整math.Floor()
//go没有其他语言得round函数,整数位得四舍五入简单版 func round(x float64){ return int(math.Floor(x + 0/5)) }
package main
import (
"fmt"
"github.com/shopspring/decimal"
)
/*
保有小数位得四舍五入
*/
func main() {
v1, _ := decimal.NewFromFloat(9.824).Round(2).Float64()
v2, _ := decimal.NewFromFloat(9.826).Round(2).Float64()
v3, _ := decimal.NewFromFloat(9.8251).Round(2).Float64()
fmt.Println(v1, v2, v3)
v4, _ := decimal.NewFromFloat(9.815).Round(2).Float64()
v5, _ := decimal.NewFromFloat(9.825).Round(2).Float64()
v6, _ := decimal.NewFromFloat(9.835).Round(2).Float64()
v7, _ := decimal.NewFromFloat(9.845).Round(2).Float64()
fmt.Println(v4, v5, v6, v7)
v8, _ := decimal.NewFromFloat(3.3).Round(2).Float64()
v9, _ := decimal.NewFromFloat(3.3000000000000003).Round(2).Float64()
v10, _ := decimal.NewFromFloat(3).Round(2).Float64()
fmt.Println(v8, v9, v10)
v11, _ := decimal.NewFromFloat(129.975).Round(2).Float64()
v12, _ := decimal.NewFromFloat(34423.125).Round(2).Float64()
fmt.Println(v11, v12)
}
9 - 文件目录操作函数
获取指定目录下正则匹配到的文件
package main
import (
"fmt"
"log"
"os"
"path/filepath"
)
func main() {
files, err := WalkMatch("./", "*.exe")
if err != nil {
log.Fatalln(err)
}
fmt.Println(files)
}
func WalkMatch(root, pattern string) ([]string, error) {
var matches []string
err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if info.IsDir() {
return nil
}
if matched, err := filepath.Match(pattern, filepath.Base(path)); err != nil {
return err
} else if matched {
path, _ = filepath.Abs(path)
matches = append(matches, path)
}
return nil
})
if err != nil {
return nil, err
}
return matches, nil
}
10 - 系统变量初始化
Context
ctx, _ := context.WithTimeout(context.Background(), 15 * time.Second)
获取当前路径
package main
import (
"os"
"path/filepath"
)
func main() {
// 据说这个方法在某些特别场景会获取到错误的路径
dir1, _ := os.Getwd()
//推荐使用下面的方法
dir2, _ := os.Executable()
exPath := filepath.Dir(dir2)
println(exPath2)
}
11 - 序列化
序列化存入内存
f,err = os.Open("path")
if err != nil {
driver.logger.Error("文件打开失败:"+err.Error())
os.Exit(-1)
}
dec := gob.NewDecoder(f)
err = dec.Decode(&helper.DeviceTerminalMap)
//判断有错误并且不是文件为空的错误,文件如果为空,在读文件是直接返回文件结束符(EOF)
if err != nil && err != io.EOF {
driver.logger.Error("设备终端档案存储文件解析失败:"+err.Error())
os.Exit(-1)
}
写入序列化内容
f, _ := os.Open("device-terminal.god")
defer f.Close()
dec := gob.NewDecoder(f)
err = dec.Decode(&helper.DeviceTerminalMap)
12 - 整型
int64 -> string
var i1 int64
i1 = 555
str1 := strconv.FormatInt(int1,10)
int -> string
i2 := 1
str2 := strconv.Itoa(i2)
int8 -> string
var int8Value int8
int8Value = 2
strconv.Itoa(int(int8Value))
//整形转换成字节
func IntToBytes(n int) []byte {
x := int32(n)
bytesBuffer := bytes.NewBuffer([]byte{})
binary.Write(bytesBuffer, binary.BigEndian, x)
return bytesBuffer.Bytes()
}
//字节转换成整形
func BytesToInt(b []byte) int {
bytesBuffer := bytes.NewBuffer(b)
var x int32
binary.Read(bytesBuffer, binary.BigEndian, &x)
return int(x)
}
13 - 字符串函数
生成UUID
package main
import (
"github.com/satori/go.uuid"
"fmt"
)
func main(){
u1 := uuid.Must(uuid.NewV4())
fmt.Printf("UUIDv4:%s\n", u1)
u2, err := uuid.FromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8")
if err != nil {
fmt.Printf("Something went wrong: %s", err)
return
}
fmt.Printf("Successfully parsed: %s", u2)
}
字符串拆分
//1. 按指定字符拆分
s := "iiaiibiiciiiidiiii"
sep:="ii"
arr:=strings.Split(s,sep)
fmt.Println("arr:",arr)
//2. 按空格拆分
s:=" ab cd ef gh ij kl "
arr:=strings.Fields(s)
fmt.Printf("arr:%q\n",arr)
接收gbk编码的中文要转成utf8的中文
//github.com/axgle/mahonia
func ConvertToString(src string, srcCode string, tagCode string) string {
srcCoder := mahonia.NewDecoder(srcCode)
srcResult := srcCoder.ConvertString(src)
tagCoder := mahonia.NewDecoder(tagCode)
_, cdata, _ := tagCoder.Translate([]byte(srcResult), true)
result := string(cdata)
return result
}
func main() {
//gbk编码的中文,用16进制字符串表示
hex_str := "4d6f646275732e58464a2e3330462ec0e4c4fdcbaec5c5cbaeb1c3"
hex_data, _ := hex.DecodeString(hex_str)
// 将 byte 转换 为字符串 输出结果
str := ConvertToString(string(hex_data), "gbk", "utf-8")
fmt.Println(str)
//先试试这个,一般就可以了
s1 := "4d6f646275732e58464a2e3330462ec0e4c4fdcbaec5c5cbaeb1c3"
hex_data, _ := hex.DecodeString(s1)
srcCoder := mahonia.NewDecoder("gbk")
srcResult := srcCoder.ConvertString(string(hex_data))
fmt.Println(srcResult)
}
MD5
package main
import (
"crypto/md5"
"fmt"
"io"
)
func main() {
str := "abc123"
//方法一
data := []byte(str)
has := md5.Sum(data)
md5str1 := fmt.Sprintf("%x", has) //将[]byte转成16进制
fmt.Println(md5str1)
//方法二
w := md5.New()
io.WriteString(w, str) //将str写入到w中
md5str2: = fmt.Sprintf("%x", w.Sum(nil)) //w.Sum(nil)将w的hash转成[]byte格式
fmt.Println(mdtstr2)
}
Base64
package main
import (
"encoding/base64"
"fmt"
)
func main() {
//标准base64编码
data:="abckagfd*^&&^*fadf";
sEnc:=base64.StdEncoding.EncodeToString([]byte(data))
fmt.Println(sEnc)
sDec,_:=base64.StdEncoding.DecodeString(sEnc)
fmt.Println(string(sDec))
//兼容base64编码
uEnc:=base64.URLEncoding.EncodeToString([]byte(data))
fmt.Println(uEnc)
uDec,_:=base64.URLEncoding.DecodeString(uEnc)
fmt.Println(string(uDec))
}
字符串和[]byte相互转换
package main
import (
"fmt"
"reflect"
"time"
"unsafe"
)
//零拷贝字符串转字节数组
func string2bytes(s string) []byte {
stringHeader := (*reflect.StringHeader)(unsafe.Pointer(&s))
var b []byte
pbytes := (*reflect.SliceHeader)(unsafe.Pointer(&b))
pbytes.Data = stringHeader.Data
pbytes.Len = stringHeader.Len
pbytes.Cap = stringHeader.Len
return b
}
//零拷贝字节数组转字符串
func bytes2string(b []byte) string {
bHeader := (*reflect.SliceHeader)(unsafe.Pointer(&b))
var s string
stringHeader := (*reflect.StringHeader)(unsafe.Pointer(&s))
stringHeader.Data = bHeader.Data
stringHeader.Len = bHeader.Len
return s
}
func main() {
s := "零拷贝转换字符串和字节数组"
t1 := time.Now().Nanosecond()
v := string2bytes(s)
t2 := time.Now().Nanosecond()
fmt.Println(v)
t3 := time.Now().Nanosecond()
data := []byte(s)
t4 := time.Now().Nanosecond()
fmt.Println(data)
fmt.Println("method1 time", t2-t1)
fmt.Println("method2 time", t4-t3)
t5 := time.Now().Nanosecond()
s1 := bytes2string(v)
t6 := time.Now().Nanosecond()
fmt.Println(s1)
t7 := time.Now().Nanosecond()
s2 := string(v)
t8 := time.Now().Nanosecond()
fmt.Println(s2)
fmt.Println("method3 time", t6-t5)
fmt.Println("method4 time", t8-t7)
}
14 - 字节数组操作([]byte)
//isSymbol表示有无符号
func BytesToInt(b []byte, isSymbol bool) (int, error){
if isSymbol {
return bytesToIntS(b)
}
return bytesToIntU(b)
}
//字节数(大端)组转成int(无符号的)
func bytesToIntU(b []byte) (int, error) {
if len(b) == 3 {
b = append([]byte{0},b...)
}
bytesBuffer := bytes.NewBuffer(b)
switch len(b) {
case 1:
var tmp uint8
err := binary.Read(bytesBuffer, binary.BigEndian, &tmp)
return int(tmp), err
case 2:
var tmp uint16
err := binary.Read(bytesBuffer, binary.BigEndian, &tmp)
return int(tmp), err
case 4:
var tmp uint32
err := binary.Read(bytesBuffer, binary.BigEndian, &tmp)
return int(tmp), err
default:
return 0,fmt.Errorf("%s", "BytesToInt bytes lenth is invaild!")
}
}
//字节数(大端)组转成int(有符号)
func bytesToIntS(b []byte) (int, error) {
if len(b) == 3 {
b = append([]byte{0},b...)
}
bytesBuffer := bytes.NewBuffer(b)
switch len(b) {
case 1:
var tmp int8
err := binary.Read(bytesBuffer, binary.BigEndian, &tmp)
return int(tmp), err
case 2:
var tmp int16
err := binary.Read(bytesBuffer, binary.BigEndian, &tmp)
return int(tmp), err
case 4:
var tmp int32
err := binary.Read(bytesBuffer, binary.BigEndian, &tmp)
return int(tmp), err
default:
return 0,fmt.Errorf("%s", "BytesToInt bytes lenth is invaild!")
}
}
//整形转换成字节
func IntToBytes(n int,b byte) ([]byte,error) {
switch b {
case 1:
tmp := int8(n)
bytesBuffer := bytes.NewBuffer([]byte{})
binary.Write(bytesBuffer, binary.BigEndian, &tmp)
return bytesBuffer.Bytes(),nil
case 2:
tmp := int16(n)
bytesBuffer := bytes.NewBuffer([]byte{})
binary.Write(bytesBuffer, binary.BigEndian, &tmp)
return bytesBuffer.Bytes(),nil
case 3,4:
tmp := int32(n)
bytesBuffer := bytes.NewBuffer([]byte{})
binary.Write(bytesBuffer, binary.BigEndian, &tmp)
return bytesBuffer.Bytes(),nil
}
return nil,fmt.Errorf("IntToBytes b param is invaild")
}