为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
RISEBY 2023-07-04 17:04:33
我对 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 技巧。使用字符串生成器是否更好?有没有一种方法可以以反射方式迭代结构体的所有字段并将它们连接起来?
查看完整描述

4 回答

?
蝴蝶不菲

TA贡献1810条经验 获得超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)获取一个字符串。


查看完整回答
反对 回复 2023-07-04
?
三国纷争

TA贡献1804条经验 获得超7个赞

我认为您会想使用 Stringer 接口。IE:


package main


import (

  "fmt"

  "strings"

  "strconv"

)

type Employee struct {

    Name        string

    Designation string

    Department  string

    Salary      int

    Email       string

}

func main() {

  emp1:=Employee{Name:"Cetin", Department:"MS", Salary:50}

  emp2:=Employee{Name:"David", Designation:"Designation", Email:"david@nowhere.com"}

  emp3:=Employee{Department:"Space", Salary:10}


  fmt.Println(emp1)

  fmt.Println(emp2)

  fmt.Println(emp3)


}


func (e Employee) String() string {

    var salary string

    if e.Salary > 0 { 

      salary = strconv.Itoa(e.Salary) + " " 

    } else {

      salary = ""

    }

    return strings.TrimSpace(

        strings.TrimSpace(

        strings.TrimSpace(e.Name + " " + e.Designation) + " " +

        e.Department) + " " +

    salary +

        e.Email)

}

游乐场:https://play.golang.org/p/L8ft7SeXpqt


PS:我后来注意到你只想要字符串字段,但无论如何都没有删除工资。


查看完整回答
反对 回复 2023-07-04
?
一只萌萌小番薯

TA贡献1795条经验 获得超7个赞

您可以通过编写一个实用函数来通过“非空白字符串”检查进行添加来使其不那么冗长。


另外,您可以让您的类型实现一个String()方法,该方法的优点是在fmt打印函数中使用时可以按照您的意愿进行打印。


此addToString函数是通用的,因此如果对其他类型执行此操作,您可以重用它:


func addToString(original string, addition interface{}) string {

    additionStr := fmt.Sprint(addition)

    if additionStr != "" {

        if original != "" {

            original += " "

        }

        original += additionStr

    }

    return original

}

然后你可以像这样实现它,这不是那么冗长:


type Employee struct {

    Name        string

    Designation string

    Department  string

    Salary      int

    Email       string

}


func (e *Employee) String() string {

    theString := ""

    theString = addToString(theString, e.Name)

    theString = addToString(theString, e.Designation)

    theString = addToString(theString, e.Department)

    theString = addToString(theString, e.Salary)

    theString = addToString(theString, e.Email)

    return theString

}

并像这样使用它:


func main() {

    emp := &Employee{

        Name: "Jonh",

        Department: "Some dept",

    }

    fmt.Println(emp.String())

    fmt.Println(emp)

}

这将输出:


Jonh Some dept 0

Jonh Some dept 0


查看完整回答
反对 回复 2023-07-04
?
有只小跳蛙

TA贡献1824条经验 获得超8个赞

封装 fmt

import "fmt"

类型纵梁

Stringer 由具有 String 方法的任何值实现,该方法定义该值的“本机”格式。String 方法用于将作为操作数传递的值打印到任何接受字符串的格式或打印到未格式化的打印机(例如 Print)。

type Stringer interface {
        String() string}

String为 type编写一个方法Employee

例如,

package main


import (

    "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 中相同的错误。返回的值是在运行时而不是编译时确定的。

如果您的情况,业务要求是隐藏机密字段,例如工资,并将显示的字段限制为几个关键的描述性字段。不可避免地,字段将被添加到结构中。“连接字符串字段”规范现在或将来不太可能是正确的。


查看完整回答
反对 回复 2023-07-04
  • 4 回答
  • 0 关注
  • 174 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信