Search code examples
gostructreflect

How to transform any string in struct field name like


I would like to know if there is a native way to transform strings like:

  • a.string
  • a-string
  • a_string
  • a string

In a string that follows the convention for public field members of structs, in Go.

The idea is to write a function that accepts a string and try to get the value of the field, even if the passed string is not using the PascalCase convention, example:

type MyStruct struct {
    Debug   bool
    AString bool
    SomethingMoreComplex
}

var myStruct MyStruct

func GetField(s string) reflect.Value {
   v := reflect.ValueOf(myStruct)
   return v.FieldByName(s)
}

function main() {
    GetField("debug")
    GetField("a.string")
    GetField("a-string")
    GetField("a_string")
    GetField("-a.string")
    GetField("something-more-complex")
}

I was using the strcase package, but it only works for ASCII.


Solution

  • By the magic of regular expressions

    https://goplay.space/#xHfxG249CsH

    package main
    
    import (
        "fmt"
        "regexp"
        "strings"
    )
    
    func ConvertFieldName(s string) string {
        r := regexp.MustCompile("(\\b|-|_|\\.)[a-z]")
        return r.ReplaceAllStringFunc(s, func(t string) string {
            if len(t) == 1 {
                return strings.ToUpper(t)
            } else {
                return strings.ToUpper(string(t[1]))
            }
    
        })
    
    }
    
    func main() {
        fmt.Println(ConvertFieldName("debug"))
        fmt.Println(ConvertFieldName("a.string"))
        fmt.Println(ConvertFieldName("a-string"))
        fmt.Println(ConvertFieldName("a_string"))
        fmt.Println(ConvertFieldName("-a.string"))
        fmt.Println(ConvertFieldName("something-more-complex"))
    }
    

    Outputs

    Debug
    AString
    AString
    AString
    AString
    SomethingMoreComplex