go接口转字符串
Go接口转化为字符串,这几个方法别不要不知道了
被爱的人不需要say sorry
女生那些闹小脾气,撒娇,不理你的行为,其实是在向你表达:你快来抱抱我
要让别人爱上你,首先自己要能爱自己
时间太久了,久到我以为真的是后会无期
当提到接口,我们已经知道它是用来设计系统的大杀器。接口定义了做某件事情的一种路径和指引,就像你和几个朋友国庆去九寨沟旅游的时候,会做一个旅游攻略。其实我们会发现这样的攻略往往具有某种通用性,因为别人也会有和你一样的攻略。这个特点就是可复用(reusable code)。
上面的旅游攻略,没有多余的文字细节描述,表达出很简洁的路径。那些被标识出来的节点,就是接口需要做的事情。然而不同的人对同样攻略的实现也不尽相同。虽然是面对一样的风景,感受和行为也会不一样。这就是实现细节的灵活性(flexible code)。
go给人的感觉是不太容易让人想到把一个接口转为字符串这样的表达形式。这点和java不同,java的顶级类Object里面就有toString这样的方法来对对象进行字符串表达。这和java自身强调自己是面向对象语言有很深的关系。go里面对应的顶级类型是interface{},go不再说自己是面向对象的,用这样的表达方式来强调面向接口的设计原则。
从类型系统的顶级设计来看,go的设计更为简洁。其缺点也很明显,就是对类似toString这样常用的行为表达就缺失了。
使用fmt包
fmt的Springf方法可以用来格式化打印一个变量,返回一个字符串,当然也包含我们这里说的接口。
var i interface{} = 42
str := fmt.Sprintf("%v", i) // 42
如果你对接口潜在的类型有明确的想法,也可以进行类型断言之后再进行打印
var i interface{} = 42
if val, ok := i.(int); ok {
str := fmt.Sprintf("%d", val)
}
这个方式需要记住关于fmt格式化的一些规则,会有一定的记忆负担。
使用encoding/json包
go的encoding/json提供了接口与json字符串的互转,不过这个方法先得到的是byte切片,这是string底层的表示,可以调用string()来转为string。
Example:
var i interface{} = 42
jsonBytes, _ := json.Marshal(i)
str := string(jsonBytes)
使用自定义的Stringer接口
Stringer接口也在fmt包里面,通过实现这个接口来自定义把接口转为字符串。这个方式可以让你对接口的字符串表达进行自定义表达。
Stringer
type Stringer interface {
String() string
}
type MyInterface struct {
value int
}
//实现了String()
func (mi MyInterface) String() string {
//这里可以选择任何一种转化为字符串的方法,包括自己定义的方法
//比如 return "value="+mi.value
return fmt.Sprintf("%d", mi.value)
}
var i fmt.Stringer = MyInterface{value: 42}
str := i.String()
类型里面包含枚举类型转为string
定义一个包含枚举的类型Dog
type Breed int
const (
Poodle Breed = iota
Beagle
Labrador
Pug
)
type Dog struct {
name string
breed Breed
}
//自定义
func (d Dog) String() string {
return fmt.Sprintf("My name is %s, I'm a %s! Woof!",
d.name, d.breed)
}
这样做会得到一个奇怪的字符串
func main() {
d := dog.Dog{"Rex", dog.Poodle}
//output:My name is Rex, I'm a %!s(main.Breed=0)! Woof!
fmt.Print(d)
}
原因是枚举没有实现Stringer接口,所以打印出这样的信息,所以我们还是实现下
func (b Breed) String() string {
switch b {
//卷毛狗
case Poodle: return "poodle"
//小猎兔狗
case Beagle: return "beagle"
// and so on...
}
}