如何连接忽略空字符串的结构的字符串字段?
How to concat the string fields of a struct ignoring the empty strings?
我是 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[:], " ")
我认为这种方法非常冗长并且缺乏围棋技巧。
改用字符串生成器更好吗?
有没有办法以反射的方式遍历结构的所有字段并将它们连接起来?
您可以通过编写一个实用函数来使 "non-blank-string" 检查加法变得不那么冗长。
此外,您可以让您的类型实现实现一个 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
我认为您会希望改用 Stringer 接口。即:
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:我后来注意到你只想要字符串字段,但并没有删除工资。
import "fmt"
Stringer is implemented by any value that has a String method, which
defines the “native” format for that value. The String method is used
to print values passed as an operand to any format that accepts a
string or to an unformatted printer such as Print.
type Stringer interface {
String() string
}
为类型Employee
写一个String
方法。
例如,
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
I want to concatenate the string fields into a type of employee
description.
Is there a way to iterate through all fields of a struct in a
Reflection way and join them?
[反射是]一个强大的工具,除非绝对必要,否则应谨慎使用并避免使用。罗伯·派克
The Go Blog: The Laws of Reflection
倒影永远不清晰。罗伯·派克
Go Proverbs - Rob Pike - Gopherfest - November 18, 2015
Go 编译的代码是高效的。 Go 反射包函数在 运行 时间被解释。
迭代结构的所有字段与 SQL 中的 SELECT * FROM table;
存在相同的错误。返回的值是在 运行 时确定的,而不是编译时。
如果你的情况,业务需求是隐藏机密字段,如工资,并将显示的字段限制为几个关键的描述性字段。不可避免地,字段将被添加到结构中。 "concatenate the string fields" 规范现在或将来不太可能正确。
遍历字符串字段并收集 non-empty 个字符串。加入字段。
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.
的应用程序代码没有任何好处
以下是如何使用反射来避免在字符串函数中列出字段:
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, " ")
}
如果你想包含所有字段(包含non-strings和空字符串),那么你可以fmt.Sprint(e)
得到一个字符串。参见 https://play.golang.org/p/yntZxQ-Xs6C。
我是 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[:], " ")
我认为这种方法非常冗长并且缺乏围棋技巧。 改用字符串生成器更好吗? 有没有办法以反射的方式遍历结构的所有字段并将它们连接起来?
您可以通过编写一个实用函数来使 "non-blank-string" 检查加法变得不那么冗长。
此外,您可以让您的类型实现实现一个 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
我认为您会希望改用 Stringer 接口。即:
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:我后来注意到你只想要字符串字段,但并没有删除工资。
import "fmt"
Stringer is implemented by any value that has a String method, which defines the “native” format for that value. The String method is used to print values passed as an operand to any format that accepts a string or to an unformatted printer such as Print.
type Stringer interface { String() string }
为类型Employee
写一个String
方法。
例如,
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
I want to concatenate the string fields into a type of employee description.
Is there a way to iterate through all fields of a struct in a Reflection way and join them?
[反射是]一个强大的工具,除非绝对必要,否则应谨慎使用并避免使用。罗伯·派克
The Go Blog: The Laws of Reflection
倒影永远不清晰。罗伯·派克
Go Proverbs - Rob Pike - Gopherfest - November 18, 2015
Go 编译的代码是高效的。 Go 反射包函数在 运行 时间被解释。
迭代结构的所有字段与 SQL 中的 SELECT * FROM table;
存在相同的错误。返回的值是在 运行 时确定的,而不是编译时。
如果你的情况,业务需求是隐藏机密字段,如工资,并将显示的字段限制为几个关键的描述性字段。不可避免地,字段将被添加到结构中。 "concatenate the string fields" 规范现在或将来不太可能正确。
遍历字符串字段并收集 non-empty 个字符串。加入字段。
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.
的应用程序代码没有任何好处以下是如何使用反射来避免在字符串函数中列出字段:
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, " ")
}
如果你想包含所有字段(包含non-strings和空字符串),那么你可以fmt.Sprint(e)
得到一个字符串。参见 https://play.golang.org/p/yntZxQ-Xs6C。