golang--随笔1
方法名定义:
golang定义一个方法,方法名首字母小写,代表私有的,方法名大写,代表共有的
获取时间:
strconv.Itoa(int(time.Now().Unix()))//获取当前时间戳 //获取指定多久前的时间戳: case 15://15分钟 second = 30 * 60 break case 30://30分钟 second = 60 * 60 break end_date := strconv.Itoa(int((time.Now().Unix() - second) * 1000))
将数组进行json加密
string,err:=json.Marshal(数组)
将json加密后的数组转化成数组类型:
myMap := make(map[string]interface{}) map[string]中string代表下标都是string型,interface代表,values值可以随机(字符/int/...)
json.Unmarshal([]byte(加密后的结果), &myMap)
MD5加密:
w := md5.New() io.WriteString(w,要加密的字符) 输出加密后的值:fmt.Sprintf("%x",w.Sum(mil))
字符串拼接:
用+
或者:bytes.NewBufferString("") buffer .writeString(字符) 获取拼接好的字符:buffer.String
查询变量数据类型
reflect.TypeOf(变量)
定义key=>value数组时
要先用a:=make(map['string']string)定义一个类型
然后a["a"] = "c"
make和new的区别:
make只用于slice/map/channel的初始化,初始化时会初始化内部结构,返回的是初始化后的类型而非指针
new用于任何类型,初始化只分配内存填0值,返回的是指向0的指针
// make 示例 s := make([]int, 3, 5) // 返回 []int,len=3, cap=5 m := make(map[string]int) // 返回 map,可以立即使用 ch := make(chan int, 10) // 返回 chan,缓冲区10 // new 示例 p := new(int) // 返回 *int,指向 0 slicePtr := new([]int) // 返回 *[]int,指向 nil slice // 常见错误 var p *[]int = new([]int) // 分配了 slice header,但底层数组是 nil (*p) = append(*p, 1) // 可以使用,但不常见
rune和byte的区别
byte是Ascll字符(1字节),rune是unicode字符(4字节)。处理中文等多字节字符时必须用rune,否则会出现乱码或长度错误
// byte = uint8,ASCII 字符
var b byte = 'A' // 65
var b2 byte = '中' // 错误 '中' 占 3 字节
// rune = int32,Unicode 码点
var r rune = '中' // 20013
var r2 rune = 'A' // 65
// 实际应用:处理中文
s := "Hello 世界"
fmt.Println(len(s)) // 12 (H e l l o 空格 世 界 = 5+1+3+3=12)
fmt.Println(utf8.RuneCountInString(s)) // 8
// 遍历字符串的正确方式
for i, ch := range s { // range 自动按 rune 遍历
fmt.Printf("%d: %c\n", i, ch)
}
// 输出:
// 0: H
// 1: e
// 2: l
// 3: l
// 4: o
// 5:
// 6: 世
// 9: 界
panic和recover的机制:
panic是程序遇到无法处理的错误时主动崩溃的,recover只能在defer函数中捕获panic,用于防止程序完全崩溃,常用于HTTP框架中隔离单个请求panic
因:panic会沿着调用栈向上传播,直到被recover捕获或程序崩溃;recover只能在defer函数中生效
sync.Map与普通map+锁的区别:
sync.map通过读写分离和延迟删除来优化,适合读多写少且key集合相对稳定的场景
普通map+锁更适合频繁写操作或key变化大的场景
// 普通 map + RWMutex(适合读多写少)
type SafeMap struct {
mu sync.RWMutex
m map[string]int
}
func (s *SafeMap) Get(key string) int {
s.mu.RLock()
defer s.mu.RUnlock()
return s.m[key]
}
// sync.Map(适合:读多写少 + key 集合稳定)
var m sync.Map
// 写入
m.Store("key", 42)
// 读取
if val, ok := m.Load("key"); ok {
fmt.Println(val.(int))
}
// 删除
m.Delete("key")
// 遍历
m.Range(func(key, value interface{}) bool {
fmt.Println(key, value)
return true // 返回 false 停止遍历
})
select 机制和随机性:
select会随机选择一个可用的case执行(避免饥饿),没有可用case且没有default时会阻塞;常用于超市控制,非阻塞操作,多路复用和退出信号监听
// select 用于多路监听 channel
func selectExample() {
ch1 := make(chan int)
ch2 := make(chan int)
go func() { ch1 <- 1 }()
go func() { ch2 <- 2 }()
select {
case v := <-ch1:
fmt.Println("from ch1:", v)
case v := <-ch2:
fmt.Println("from ch2:", v)
default:
fmt.Println("都没有数据")
}
// 输出:随机,可能是 from ch1:1 或 from ch2:2
}
// 典型用法1:超时控制
func withTimeout() {
ch := make(chan int)
select {
case v := <-ch:
fmt.Println(v)
case <-time.After(3 * time.Second):
fmt.Println("超时了")
}
}
// 典型用法2:非阻塞操作
func nonBlocking(ch chan int) {
select {
case ch <- 42:
fmt.Println("发送成功")
default:
fmt.Println("channel 满了,跳过")
}
}
// 典型用法3:退出控制
func worker(stop <-chan struct{}) {
for {
select {
case <-stop:
fmt.Println("收到退出信号")
return
default:
// 正常干活
time.Sleep(100 * time.Millisecond)
}
}
}
iota是什么?有什么特性?
iota是一个常量计数器,只能在const声明中使用,会在每个const块中从0开始逐行递增。核心是为了生成枚举值或位掩码
itoa在const块中默认第一个是0,每增一行iota的值就+1,常用于定义有序常量,比如状态码。要注意的是在同一个const中即使使用_跳过某一行iota的值依然会递增。
go test支持的参数?性能测试如何运行?
-v :显示详细信息输出
-run:指定要运行的测试函数正则
-count:指定运行行数
-cover:显示测试覆盖率
-bench:性能测试,后面跟一个正则表达式来匹配要运行的基准测试函数名
# 运行所有测试,显示详细输出和覆盖率 go test -v -cover ./... # 运行基准测试,并输出内存分配统计 go test -bench=. -benchmem # 生成CPU性能分析文件 go test -bench=. -cpuprofile=cpu.prof
go中如何实现单例模式:
推荐使用sync.Once来实现单例模式,sync.Once的DO能保证无论被多少个goroutine并发调用,其传入的函数都只会被执行一次,这是实现线程安全懒加载的最高效方式。代码示例:
type singleton struct{}
var instance *singleton
var once sync.Once
func GetInstance() *singleton {
once.Do(func() {
instance = &singleton{}
})
return instance
}


浙公网安备 33010602011771号