Golang Go语言问题,求解答

Golang Go语言问题,求解答

最近尝试用 gin 写一个个人项目,有个问题就是,因为 golang 里用大小写控制访问权限,所以我定义的 struct 的属性名都是大写的,这样以 json 格式返回后 key 也都是首字母大写的 PascalCase 风格,但我需要 cameCase 风格,有什么办法统一处理吗?

我目前知道可以在定义 struct 的时候加json的 tag,但是一个有点麻烦,另一个就是对于一些第三方依赖包里定义的 struct 就没有办法了,有什么优雅的办法吗?


更多关于Golang Go语言问题,求解答的实战教程也可以访问 https://www.itying.com/category-94-b0.html

32 回复

请认真阅读文档:
https://github.com/gin-gonic/gin#model-binding-and-validation

如果遇到路由冲突:
https://hanggi.me/post/golang/wildcard-conflict/

当然好好设计针对 httprouter 的路由规则才是正解。

更多关于Golang Go语言问题,求解答的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


encoding/json最优雅

u1s1,个人项目用 php 一把梭不香嘛 或者你擅长的语言也可以噻

说的不是参数绑定,是返回数据啊,而且这里说的而不也是加 tag 吗

不会 php

加个 tag 有什么麻烦的, 第三方的你只能自己定义一个一样的结构体,把数据拷过来了

给第三方 struct 定义别名,并给这个别名实现 Marshaler 接口

默认就是和属性名保持一致,没毛病,要驼峰加 tag,这个做法没有问题,你的需求是个性化的。

要么自己实现对应接口,那个成本更高

原理是一样的,静态语言就是要把 json 绑定到结构体里。不要想着动态解析它,用不来可以用 nodejs,现在 typescript 开发也都要绑定结构体,一样的。

按我的想法,这个可以用一个后置的中间件,handlle 结束后做统一处理,可是没找到现成的,我试试自己写一个吧

一般的做法是在 struct 的 tag 进行处理,添加 json,里面随便定义,下划线或者驼峰方式都可以。

对 第三方 struct 应该可以用 reflect 处理

我啥时候要动态解析了,我又什么时候没绑定结构体了?你能不能认真审题

笑死了 #1 #10,一本正经的答非所问

可以找一个自动生成 tag 的结构体生成器,第三方包的话就把字段反射解析出来

https://github.com/fatih/gomodifytags 修改 tag,第三方的包的可以自己再建一个结构体,然后用 mapstructure 转换?

go 这个东西不就是这样
你都习惯别的了还纠结啥 tag

自己实现一个自用 Marshaller ?

只需要实现 Marshaler 接口并包裹一下(这篇文章中用正则表达式来处理比较低效,需要优化)
https://www.cnblogs.com/chenqionghe/p/13067596.html

我说得很清楚了,Go 是静态语言,不要想着什么 marshal 之类的优雅解决。
你要做的就是定义一个 response 结构体,把你要返回的数据 mapping 上去。
你可以用一些工具简化这个操作,但是结果都是一样的。

如果你觉得麻烦,不想这样,可以考虑使用 Nodejs 这种动态语言。

我返回的数据就是个结构体你听不听得懂人话?求你别回我了

那看起来还是转换风格比较 easy 。

VSCode go 插件有个命令:Go: Add Tags To Struct Fields

不过缺点是支持 snake_case,不知道在哪里改

好在我找到 VSCode 有个插件 change-case ,可以方便的在不认风格间切换

我觉得问题的点在于,你为什么要依赖第三方包的 struct 生成 response 。这样子是不可控的

怪心累的,听不懂人话呢,只说最后一次。

看你问这个问题就知道你没怎么用过 go 语言。你以为你是这世界上第一个有这种需求的人吗?
go 语言发展了 10 年为什么找不到你要的所谓的第三方依赖包,因为 go 语言不提倡这么做。

像 #13 楼说的 reflect 其实就是一种动态判断类型的方法,但是,不要这么做,原因自己查。

不要什么后置中间件统一处理,如果你非要这么做可能 go 语言不适合你。


go 语言 json struct 可以嵌套你知道吧?你要做的就是定义好结构体,加好 tag,组合使用他们。
如果这样还看不懂,你也不用回了。

定义 tag ?

package jsonconv

import (
“bytes”
“encoding/json”
“log”
“regexp”
“strconv”
“strings”
“unicode”
)

/*************************************** 下划线 json /
type JsonSnakeCase struct {
Value interface{}
}

func (c JsonSnakeCase) MarshalJSON() ([]byte, error) {
// Regexp definitions
var keyMatchRegex = regexp.MustCompile(\"(\w+)\":)
var wordBarrierRegex = regexp.MustCompile((\w)([A-Z]))
marshalled, err := json.Marshal(c.Value)
converted := keyMatchRegex.ReplaceAllFunc(
marshalled,
func(match []byte) []byte {
return bytes.ToLower(wordBarrierRegex.ReplaceAll(
match,
[]byte(${1}_${2}),
))
},
)
return converted, err
}

/
驼峰 json /
type JsonCamelCase struct {
Value interface{}
}

func (c JsonCamelCase) MarshalJSON() ([]byte, error) {
var keyMatchRegex = regexp.MustCompile(\"(\w+)\":)
marshalled, err := json.Marshal(c.Value)
converted := keyMatchRegex.ReplaceAllFunc(
marshalled,
func(match []byte) []byte {
matchStr := string(match)
key := matchStr[1 : len(matchStr)-2]
resKey := Lcfirst(Case2Camel(key))
return []byte(" + resKey + ":)
},
)
return converted, err
}

/
其他方法 ***************************************/
// 驼峰式写法转为下划线写法
func Camel2Case(name string) string {
buffer := NewBuffer()
for i, r := range name {
if unicode.IsUpper® {
if i != 0 {
buffer.Append(’’)
}
buffer.Append(unicode.ToLower®)
} else {
buffer.Append®
}
}
return buffer.String()
}

// 下划线写法转为驼峰写法
func Case2Camel(name string) string {
name = strings.Replace(name, "
", " “, -1)
name = strings.Title(name)
return strings.Replace(name, " “, “”, -1)
}

// 首字母大写
func Ucfirst(str string) string {
for i, v := range str {
return string(unicode.ToUpper(v)) + str[i+1:]
}
return “”
}

// 首字母小写
func Lcfirst(str string) string {
for i, v := range str {
return string(unicode.ToLower(v)) + str[i+1:]
}
return “”
}

// 内嵌 bytes.Buffer,支持连写
type Buffer struct {
*bytes.Buffer
}

func NewBuffer() *Buffer {
return &Buffer{Buffer: new(bytes.Buffer)}
}

func (b *Buffer) Append(i interface{}) *Buffer {
switch val := i.(type) {
case int:
b.append(strconv.Itoa(val))
case int64:
b.append(strconv.FormatInt(val, 10))
case uint:
b.append(strconv.FormatUint(uint64(val), 10))
case uint64:
b.append(strconv.FormatUint(val, 10))
case string:
b.append(val)
case []byte:
b.Write(val)
case rune:
b.WriteRune(val)
}
return b
}

func (b *Buffer) append(s string) Buffer {
defer func() {
if err := recover(); err != nil {
log.Println("内存不够了!
”)
}
}()
b.WriteString(s)
return b
}

func TestJsonCamelCase_MarshalJSON(t *testing.T) {
type Person struct {
HelloWold string
LightWeightBaby string
}
var a = Person{HelloWold: “xxx”, LightWeightBaby: “muscle”}
res, _ := json.Marshal(JsonCamelCase{a})
fmt.Printf(”%s", res)
}

可以,给力

你这啥理解能力?
别人已经说得很清楚了, 它定义了 struct.
而且这和静态 /动态语言有啥关系.
java 是不是静态? 一样可以指定序列号模式.

一知半解在这指点江山

当然,很高兴能帮助解答关于Go语言的问题。尽管你没有具体描述遇到的问题,但我可以根据常见的Go语言学习或开发中的疑问提供一些一般性的指导和建议。

  1. 基础语法:如果刚开始学习Go语言,建议从官方文档和教程入手,掌握基本的语法结构和核心概念,如变量、数据类型、控制结构、函数等。

  2. 并发编程:Go语言以其高效的并发处理能力著称。理解goroutines、channels以及select语句是掌握Go并发编程的关键。

  3. 标准库和第三方库:Go的标准库非常强大,涵盖了网络编程、文件操作、加密解密等多个方面。同时,也可以利用丰富的第三方库来加速开发。

  4. 错误处理:Go语言强调显式错误处理,使用多返回值来传递错误信息。熟悉这种模式对于编写健壮的代码至关重要。

  5. 构建和测试:利用Go的工具链(如go build、go test)可以方便地构建和测试项目。编写单元测试是确保代码质量的重要手段。

  6. 性能调优:了解Go的运行时机制和垃圾回收机制,有助于进行性能调优。使用性能分析工具(如pprof)可以帮助识别性能瓶颈。

如果遇到了具体的编程问题,欢迎详细描述错误信息或代码片段,以便提供更精确的帮助。希望这些建议能对你有所帮助!

回到顶部