目录
1,并发
var count int = 0
func Count() {
logger.Info("执行count=====================")
go add()
go add()
go add()
go add()
go add()
go add()
go add()
go add()
go add()
go add()
go add()
for{
if count==3{
break
}
}
logger.Info("get the end count : ",count)
}
func add() {
count++
}
2,时间的转换
package main
import (
"time"
"fmt"
)
func main() {
//获取当前时间
t := time.Now() //2018-07-11 15:07:51.8858085 +0800 CST m=+0.004000001
fmt.Println(t)
//获取当前时间戳
fmt.Println(t.Unix()) //1531293019
//获得当前的时间
fmt.Println(t.Uninx().Format("2006-01-02 15:04:05")) //2018-7-15 15:23:00
//时间 to 时间戳
loc, _ := time.LoadLocation("Asia/Shanghai") //设置时区
tt, _ := time.ParseInLocation("2006-01-02 15:04:05", "2018-07-11 15:07:51", loc) //2006-01-02 15:04:05是转换的格式如php的"Y-m-d H:i:s"
fmt.Println(tt.Unix()) //1531292871
//时间戳 to 时间
tm := time.Unix(1531293019, 0)
fmt.Println(tm.Format("2006-01-02 15:04:05")) //2018-07-11 15:10:19
//获取当前年月日,时分秒
y := t.Year() //年
m := t.Month() //月
d := t.Day() //日
h := t.Hour() //小时
i := t.Minute() //分钟
s := t.Second() //秒
fmt.Println(y, m, d, h, i, s) //2018 July 11 15 24 59
}
//注意一个问题,时间的转换单位是秒
target := time.Unix(1586223592, 0)
format := target.Format("2006-01-02 15:12:00")
logger.Info("时间戳的时间是:",format)
时间处理:https://www.jb51.net/article/164869.htm
//这里需要注意的问题是,时间转换只有秒和纳秒,没有毫秒
3,redis操作大全
总结:
go对redis的操作非常友好,do后面直接使用redis的指令,所以涉及到redis操作的时候,直接查找redis的指令大全就可以了
1,zset操作
https://blog.csdn.net/robertkun/article/details/78733660
https://www.cnblogs.com/zhaohaiyu/p/11626969.html
2,redis大全
https://www.cnblogs.com/wdliu/p/9330278.html
注意,zset有一个巨坑
从网上的ZADD是key后没有有一个字符串,实际操作测试,不需要这个字符串。另外,在获取区间的时候,注意zrangebyscore,而不是使用zrange
conn := util.TaskRedisConnPool.Get()
defer conn.Close()
r, err := conn.Do("ZADD", "mykey",123,"value")
logger.Info("==========r:",r)
if err != nil {
fmt.Println("redis set failed:", err)
}
reply, err := redis.Strings(conn.Do("zrangebyscore", "mykey", 1, 125))
if err != nil {
fmt.Println("redis get failed:", err)
} else {
fmt.Printf("Get mykey: %v \n",reply)
}
4,go的swich
对于java而言,多个case相同操作的时候,只要不退出即可往下走,但是go是默认在下一个case之前实现退出的,所以这个时候如果case后面没有操作语句,则将直接退出了。go的多个case统一操作的正确用法:
switch target{
case "aa","bb" :
fmt.Println("aa,bb")
}
5,字符串的拼接
func TestArrayJson(t *testing.T) {
var build strings.Builder
build.WriteString("a")
build.WriteString(",")
build.WriteString("b")
t.Log("show:",build.String())
}
6,复杂的结构体
为了避免创建特别多的var
第一种方式是采用一个最终的生成对象,而且尽量要容纳多的信息
h := ¶m.AdminHeader{Context: param.TokenHeader{Jsns: "urn:zimbraAdmin", AuthToken: param.AuthToken{Content: token}}}
第二种方式,也是推荐的方式,采用内置方法
var inputKafka yaml_struct.InputKafka
inputKafka.Setting(addresses, "", "", "", "", 0)
func (k *InputKafka) Setting(address []string, topic, consumerGroup, clientId, targetVersion string, partition int32) {
k.Kafka = Kafka{Addresses: address, Topic: topic, ConsumerGroup: consumerGroup, Partition: partition, ClientId: clientId, TargetVersion: targetVersion}
}
type InputKafka struct {
Kafka Kafka `json:"kafka"`
}
type Kafka struct {
Addresses []string `json:"Addresses"`
Topic string `json:"topic"`
ConsumerGroup string `json:"consumer_group"`
Partition int32 `json:"partition"`
ClientId string `json:"client_id"`
TargetVersion string `json:"target_version"`
}
判断是否为空实例
reflect.DeepEqual(one, model.UserBizid{})
字符串的开头
strings.Index(b, “ecp”) == 0
如果是不包含就是-1
在判断是否包含某个字段的判断,目前只有map是确定的,如果是强转后判断,接收对象是interface,可能会出现错误,看下面例子
if infos, ok := info.Config.Definition[taskKey].([]interface{}); ok && infos != nil {
groupInfos = infos
}
这个判断一定能成功,即使不存在taskKey也能成功,因为后面接的是interface,泛型,包括空
所以修改成以下
if infos, ok := info.Config.Definition[taskKey]; ok && infos != nil {
groupInfos = infos.(primitive.A)
}
排序
sort.Sort(sort.StringSlice(nodeNames))
err日志独立存储
在接口出现宕机的时候,如果是ide,会发现控制台打印了宕机的数据,但是linux如何保存这些宕机的日志呢
看下面go的main包启动
#!/bin/bash
chmod +x main
nohup ./main 2>err.log &
这里涉及到nohup脚本命令,1是stdout标准输出,2是stderr错误输出,详细介绍看
https://blog.csdn.net/origin_lee/article/details/41576975 描述这两者的区别
高并发下append出现线程不安全
在高并发下append线程不安全,原因可以自己查
lock.Lock()
collaboration.Groups = append(collaboration.Groups, group)
lock.Unlock()