头像

SolitudeAlma




离线:3小时前


最近来访(1058)
用户头像
老陈酒
用户头像
XuandYu
用户头像
hongk_bb
用户头像
春上村樹
用户头像
我不明智
用户头像
柠檬草的味道
用户头像
kkop
用户头像
熠丶
用户头像
coder_xi
用户头像
Acwer
用户头像
派大星
用户头像
阿飞被注册了
用户头像
宇哥
用户头像
有机物
用户头像
Bi08xw
用户头像
某位不愿透露姓名的金发小女孩
用户头像
我是菜狗啊啊啊啊啊
用户头像
Gzyymz
用户头像
dqwd
用户头像
yxc的小迷妹


SolitudeAlma
10小时前

来源

简单来说就是拷贝的是一样结构的结构体,而结构体的字段一个是指向底层的指针,所以代价也只是拷贝指针的代价,另外两个并不影响copy的代价,因为他们只是一个整型变量,大家都拥有




SolitudeAlma
10小时前

题目来源
辅助阅读

我们都知道string和slice相似,都是一个结构体,引用了底层数组,并记录了自身的长度等信息。

在开始做这题前,你应该明白的几个知识点,string、rune、byte以及中文在string中的存储。

string的底层其实就是字节数组,也就是uint8,表示的范围有限,因此如果要正确的表示一个汉字(3个字节,Unicode),那么这个数组就会比正常的要长三倍。

在go中还有这么一个类型rune,它是int32的别名,能完整表示Unicode的所有码点,为什么不用int呢,int也是32位呀,但是int在go中,如果是32位系统它是4字节,64位系统是4字节。也就是说这是不确定的

因为byte和rune本质上没有区别,只是范围不一样,那么我们可以用rune将string转为rune数组。接着遍历数组交换头尾两个位置就行了

类似的截取带有中文的string时,一样会得到预期以外的结果。因为只截取了部分的数据,并不完整

package main

import (
    "fmt"
    "os"
    "bufio"
)

func main() {

    var s string

    reader := bufio.NewReader(os.Stdin)
    fmt.Fscan(reader, &s)

    tmp := []rune(s)

    length := len(tmp)

    for i := range tmp {
        if i == length / 2 {
            break;
        }

        tmp[i], tmp[length - i - 1] = tmp[length - i - 1], tmp[i]
    }

    fmt.Println(string(tmp))

}



Gin框架中处理请求参数的零值问题

有时候参数验证需要用到类型零值,比如bool 或是标志位(0表示xxx,1表示xxx)。
这时候gin的参数验证库对struct的 json:"xxx" binding:"required" 这个tag验证是,必须带上这个参数,并且不为零值,因为不带上的话json反序列化就是零值

所以我们可以这么做


type UserInfoReq struct {
    Username string `json:"username" binding:"required"`
    Sex      *int    `json:"sex" binding:"required"`
}

这样就能真确获取想要的数据,而不会验证失败




golang复用http.request.body
[Go - Note] http.Response.Body 多次读取处理
Gin框架,body参数只能读取一次
[go] Gin中间件中获取request.body
Gin框架参数多次绑定

具体原因无非是读取body是类似读缓存区的数据,读完之后数据就是空的,最简单的做法就是读完之后把数据放回去

buf := &bytes.Buffer{}
oldBody := io.TeeReader(ctx.Request.Body, buf)
body, err := ioutil.ReadAll(oldBody)
ctx.Request.Body = ioutil.NopCloser(bytes.NewBuffer(buf))


body, err := ioutil.ReadAll(ctx.Request.Body)
ctx.Request.Body = ioutil.NopCloser(bytes.NewBuffer(body))
ctx.Request.Body.Close() // 用完记得关掉io流 可以用defer






SolitudeAlma
1个月前

今天摸鱼写微信支付的时候遇到了这样一个问题

我用了第三方的框架PowerWeChat来处理微信的服务端api。当我处理支付回调通知时,先在函数外部定义了想要的数据,然后在内部赋值,具体的看下面的代码,你就能明白了

func xxx() {
    order := &model.Order{}

    _, err := wechat.PaymentApp.HandlePaidNotify(
        r,
        func(message *request.RequestNotify, transaction *models2.Transaction, fail func(message string)) interface{} {
            var err error
            order, err := l.orderRepo.GetOrderByTradeNo(ctx, transaction.OutTradeNo) // 从数据库查询订单信息
            logx.Infof("order:%+v, transaction:%+v,  message: %+v", order, transaction, message)
            if err != nil || order.IsEmpty() {
                logx.Errorf("获取用户开通空间的订单失败", err)
                return nil
            }
            ... 其他逻辑
        },
    )
    ... 其他逻辑
    fmt.Printf("%+v", order) // 打印为空
}

大家注意一个细节,我在函数内部调用查询订单的函数时,因为go的原因,:=形式声明的变量,只要有一个未定义过就需要加上 :,但并不会为order再次声明,看上去没什么问题,然后在xxx函数最后打印的时候order为空(非nil),也就是所有字段都是零值。

我的猜想是函数内部定义与外部相同的变量时,如果遇上了 :=,那么就会降低此变量的作用域,相当于范围变小了。

以下是我的复现代码,具体原因也没有深究,感兴趣的小伙伴可以试试,知道答案的也可以在评论区留言哦~

package main

import (
    "fmt"
)

type order struct {
    ID int
}

func a(b func()) {
    b()
}

func c() (o *order, err error) {
    o = &order{ID: 1}
    return 
}

func d() (*order) {

    e := &order{}
    // 返回创建的闭包
    a(func() {
        // e, err := c() // 输出为空
        var err error
        e, err = c()
        if err != nil {
            fmt.Println(err)
        }

        e.ID += 2
    })

    return e
}


func main() {

    e := d()

    fmt.Printf("%+v", e)
}



SolitudeAlma
1个月前

yitter/IdGenerator
golang下的UUID生成
技术译文 | UUID 很火但性能不佳?今天我们细聊一聊
MySQL8索引与调优篇7-索引优化与查询优化

如果打算使用uuid做主键,建议用纯数字且单调递增的算法,并且全局唯一,那么雪花飘移算法就是你的首选

Tips: 用自增主键做关联表建立两表之间的联系时会遇到一个问题(其实就是存在关系的两张表,把它们的自增主键拿出来,在第三张表上存起来,这在我看来是比较通用的做法),这只局限于小项目,不会涉及到扩张问题。也就是说甚至不会分库分表。因为用自增主键作为主键的表,在分布式系统中,是不那么好扩容的,如果我的系统中用了4个独立的数据库,那么在设置自增主键的自增步长时,就应该是从 1,2,3,4 开始,步长为4。这样在分布式系统中就能在数据库层面上做到全局唯一的id。但是分布式系统最大的特点就是体量大,随时都会遇到需要扩容的情况,那么数据库一扩容,重新设置步长也好说,但是之前的数据咋迁移呢?所以现在分布式系统都会用到分布式id生成的算法,在代码层面做到全局唯一,而算法通常也会有机器id作为生成id的机器标识,尽管有上限,但一般都开不了那么多机器。




SolitudeAlma
1个月前


分享 三户模型

SolitudeAlma
1个月前



SolitudeAlma
3个月前