英文:
A Sprintf with 3 arguments of different pointers type that can be nil. Ternary operator being unavaialble, how to avoid writing tens of lines?
问题
我有一个要用Sprintf
创建的字符串:
message := fmt.Sprintf("Unit %s has a Level of %v, but is of Category %v",
*entity.Name, *entity.LevelCode, *entity.CategoryCode)
在entity
中,这些变量是可以为nil
的:
Name
是一个*string
类型LevelCode
是一个*LevelCode
类型CategoryCode
是一个*CategoryCode
类型
但是如果它们有值,我想要的是这个值,而不是指针。
(例如:Unit ABC has a Level of nil, but is of Category AdministrativeUnit)
在任何语言中,我会这样写:
message := fmt.Sprintf("Unit %s has a Level of %v, but is of %v Category",
entity.Name != nil ? *entity.Name : "nil", entity.LevelCode != nil ? *entity.LevelCode : "nil", entity.CategoryCode != nil ? *entity.CategoryCode : "nil")
但是 Go 不允许三元运算符。如果我不处理nil
值,Sprintf
会抛出异常。
那么,我必须这样开始吗?
if entity.Name == nil && entity.LevelCode != nil && entity.CategoryCode != nil) {
message := "Unit nil has a Level of nil, but is of nil Category"
}
else {
if entity.Name != nil && entity.LevelCode != nil && entity.CategoryCode != nil) {
message := fmt.Sprintf("Unit %s has a Level of nil, but is of nil Category",
entity.Name != nil ? *entity.Name : "nil")
}
else {
...
// 对于9种可能的nil或非nil值的组合,以及9种sprintf格式,需要编写大量的代码。
}
}
有没有更简洁的方式来以格式化的方式输出变量的内容?
<details>
<summary>英文:</summary>
I have this string to create with a `Sprintf`
```go
message := fmt.Sprintf("Unit %s has a Level of %v, but is of Category %v",
*entity.Name, *entity.LevelCode, *entity.CategoryCode)
In entity, the variables are pointers that can be nil
:
Name
is a*string
LevelCode
has a*LevelCode
typeCategoryCode
has a*CategoryCode
type
but if they have a value, I want this value and not the pointers.
(i.e. Unit ABC has a Level of nil, but is of Category AdministrativeUnit)
in any language, I would have wrote:
message := fmt.Sprintf("Unit %s has a Level of %v, but is of %v Category",
entity.Name != nil ? *entity.Name : "nil", entity.LevelCode != nil ? *entity.LevelCode : "nil", entity.CategoryCode != nil ? *entity.CategoryCode : "nil")
But Go doesn't allow ternary operator. And if I don't take care of nil values, Sprintf
will throw an exception.
So, do I have to start that way?
if entity.Name == nil && entity.LevelCode != nil && entity.CategoryCode != nil) {
message := "Unit nil has a Level of nil, but is of nil Category"
}
else {
if entity.Name != nil && entity.LevelCode != nil && entity.CategoryCode != nil) {
message := fmt.Sprintf("Unit %s has a Level of nil, but is of nil Category",
entity.Name != nil ? *entity.Name : "nil")
}
else {
...
for 9 combinations of values nil or not nil values, and 9 sprintf formats?
}
}
What the shortest way to dump my variables content in a formatted line?
</details>
# 答案1
**得分**: -3
谢谢,有了你的帮助,我成功地构建了这个函数。
```go
// value函数用于处理可能为空的指针,并在它们不为空时返回它们的值。
func value[T any](v *T) string {
if v != nil {
return fmt.Sprintf("%v", *v)
} else {
return "nil"
}
}
这样调用它:
message := fmt.Sprintf("Unit %s has a Level of %v, but is of %v Category",
value(entity.Name), value(entity.LevelCode), value(entity.CategoryCode))
只用了一个Sprintf
语句就完成了五个语句的工作... 但它能正常工作。
英文:
Thanks, with your help, I succeed in building the function.
// value treat pointers that can be nil, and return their values if they aren't.
func value[T any](v *T) string {
if (v != nil) {
return fmt.Sprintf("%v", *v)
} else {
return "nil"
}
}
Called that way
message := fmt.Sprintf("Unit %s has a Level of %v, but is of %v Category",
value(entity.Name), value(entity.LevelCode), value(entity.CategoryCode))
Five statements to write for single Sprintf
... But it works.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论