猿问

如何连接结构体的字符串字段而忽略空字符串?

我对 Go 很陌生,所以需要一些建议。我有一个结构:


type Employee struct {

    Name        string

    Designation string

    Department  string

    Salary      int

    Email       string

}

我想将字符串字段连接成一种员工描述。这样,我可以说: toString(employee) 并得到:


John Smith Manager Sales john.smith@example.com

我尝试获取每个字段,检查它们是否为空并将它们放入切片中并在最后加入它们


employeeDescArr := make([]string, 0, 4)

if strings.TrimSpace(value) != "" {

    append(employee.GetName(), value)

}...

return strings.Join(employeeDescArr[:], " ")


我认为这个方法非常冗长并且缺乏 Go 技巧。使用字符串生成器是否更好?有没有一种方法可以以反射方式迭代结构体的所有字段并将它们连接起来?


RISEBY
浏览 175回答 4
4回答

蝴蝶不菲

循环遍历字符串字段并收集非空字符串。加入田野。func (e *Employee) String() string {    var parts []string    for _, s := range []string{e.Name, e.Designation, e.Department, e.Email} {        if strings.TrimSpace(s) != "" {            parts = append(parts, s)        }    }    return strings.Join(parts, " ")}由于 strings.Join 函数是使用 strings.Builder 实现的,因此将 strings.Join 替换为使用 strings.Builder 的应用程序代码没有任何好处。以下是如何使用 Reflect 来避免列出字符串函数中的字段:var stringType = reflect.TypeOf("")func (e *Employee) String() string {    v := reflect.ValueOf(e).Elem()    var parts []string    for i := 0; i < v.NumField(); i++ {        f := v.Field(i)        if f.Type() == stringType {            s := f.String()            if strings.TrimSpace(s) != "" {                parts = append(parts, s)            }        }    }    return strings.Join(parts, " ")}如果你想包含所有字段(包括非字符串和空字符串),那么你可以fmt.Sprint(e)获取一个字符串。

三国纷争

我认为您会想使用 Stringer 接口。IE:package mainimport (&nbsp; "fmt"&nbsp; "strings"&nbsp; "strconv")type Employee struct {&nbsp; &nbsp; Name&nbsp; &nbsp; &nbsp; &nbsp; string&nbsp; &nbsp; Designation string&nbsp; &nbsp; Department&nbsp; string&nbsp; &nbsp; Salary&nbsp; &nbsp; &nbsp; int&nbsp; &nbsp; Email&nbsp; &nbsp; &nbsp; &nbsp;string}func main() {&nbsp; emp1:=Employee{Name:"Cetin", Department:"MS", Salary:50}&nbsp; emp2:=Employee{Name:"David", Designation:"Designation", Email:"david@nowhere.com"}&nbsp; emp3:=Employee{Department:"Space", Salary:10}&nbsp; fmt.Println(emp1)&nbsp; fmt.Println(emp2)&nbsp; fmt.Println(emp3)}func (e Employee) String() string {&nbsp; &nbsp; var salary string&nbsp; &nbsp; if e.Salary > 0 {&nbsp;&nbsp; &nbsp; &nbsp; salary = strconv.Itoa(e.Salary) + " "&nbsp;&nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; salary = ""&nbsp; &nbsp; }&nbsp; &nbsp; return strings.TrimSpace(&nbsp; &nbsp; &nbsp; &nbsp; strings.TrimSpace(&nbsp; &nbsp; &nbsp; &nbsp; strings.TrimSpace(e.Name + " " + e.Designation) + " " +&nbsp; &nbsp; &nbsp; &nbsp; e.Department) + " " +&nbsp; &nbsp; salary +&nbsp; &nbsp; &nbsp; &nbsp; e.Email)}游乐场:https://play.golang.org/p/L8ft7SeXpqtPS:我后来注意到你只想要字符串字段,但无论如何都没有删除工资。

一只萌萌小番薯

您可以通过编写一个实用函数来通过“非空白字符串”检查进行添加来使其不那么冗长。另外,您可以让您的类型实现一个String()方法,该方法的优点是在fmt打印函数中使用时可以按照您的意愿进行打印。此addToString函数是通用的,因此如果对其他类型执行此操作,您可以重用它:func addToString(original string, addition interface{}) string {&nbsp; &nbsp; additionStr := fmt.Sprint(addition)&nbsp; &nbsp; if additionStr != "" {&nbsp; &nbsp; &nbsp; &nbsp; if original != "" {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; original += " "&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; original += additionStr&nbsp; &nbsp; }&nbsp; &nbsp; return original}然后你可以像这样实现它,这不是那么冗长:type Employee struct {&nbsp; &nbsp; Name&nbsp; &nbsp; &nbsp; &nbsp; string&nbsp; &nbsp; Designation string&nbsp; &nbsp; Department&nbsp; string&nbsp; &nbsp; Salary&nbsp; &nbsp; &nbsp; int&nbsp; &nbsp; Email&nbsp; &nbsp; &nbsp; &nbsp;string}func (e *Employee) String() string {&nbsp; &nbsp; theString := ""&nbsp; &nbsp; theString = addToString(theString, e.Name)&nbsp; &nbsp; theString = addToString(theString, e.Designation)&nbsp; &nbsp; theString = addToString(theString, e.Department)&nbsp; &nbsp; theString = addToString(theString, e.Salary)&nbsp; &nbsp; theString = addToString(theString, e.Email)&nbsp; &nbsp; return theString}并像这样使用它:func main() {&nbsp; &nbsp; emp := &Employee{&nbsp; &nbsp; &nbsp; &nbsp; Name: "Jonh",&nbsp; &nbsp; &nbsp; &nbsp; Department: "Some dept",&nbsp; &nbsp; }&nbsp; &nbsp; fmt.Println(emp.String())&nbsp; &nbsp; fmt.Println(emp)}这将输出:Jonh Some dept 0Jonh Some dept 0

有只小跳蛙

封装 fmtimport "fmt"类型纵梁Stringer 由具有 String 方法的任何值实现,该方法定义该值的“本机”格式。String 方法用于将作为操作数传递的值打印到任何接受字符串的格式或打印到未格式化的打印机(例如 Print)。type Stringer interface {         String() string}String为 type编写一个方法Employee。例如,package mainimport (    "fmt"    "strings")type Employee struct {    Name        string    Designation string    Department  string    Salary      int    Email       string}func appendItem(items *strings.Builder, item string) {    if len(item) > 0 {        if items.Len() > 0 {            items.WriteByte(' ')        }        items.WriteString(item)    }}func (e Employee) String() string {    s := new(strings.Builder)    appendItem(s, e.Name)    appendItem(s, e.Designation)    appendItem(s, e.Department)    appendItem(s, e.Email)    return s.String()}func main() {    ee := Employee{        Name:        "John Smith",        Designation: "Manager",        Department:  "Sales",        Email:       "john.smith@example.com",        Salary:      42000,    }    fmt.Println(ee)}游乐场:https://play.golang.org/p/EPBjgi8usJ-输出:John Smith Manager Sales john.smith@example.com我想将字符串字段连接成一种员工描述。有没有一种方法可以以反射方式迭代结构体的所有字段并将它们连接起来?迭代结构体的所有字段具有与SELECT *  FROM table;SQL 中相同的错误。返回的值是在运行时而不是编译时确定的。如果您的情况,业务要求是隐藏机密字段,例如工资,并将显示的字段限制为几个关键的描述性字段。不可避免地,字段将被添加到结构中。“连接字符串字段”规范现在或将来不太可能是正确的。
随时随地看视频慕课网APP

相关分类

Go
我要回答