博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
golang的fmt包String(),Error(),Format(),GoString()的接口实现
阅读量:7043 次
发布时间:2019-06-28

本文共 3100 字,大约阅读时间需要 10 分钟。

简介

golang的接口使用非常广泛,几乎每一个包都会用到接口,fmt包的使用率最多之一。在实际开发中,要定义结构体的标准输出用String(),定义标准错误输出Error(),定义格式化输出Format(),还有比较特殊的GoString()。接下来描述接口的使用方式,使用场景,还有注意的地方。

String()

type TestString struct {}func (t TestString) String() string {	return "我是String"}func main() {    fmt.Println(TestString{})}复制代码
我是String复制代码

使用起来比较简单,只要结构体里面有String() string就可以输出。

fmt包里面会判断有没有fmt.Stringer的接口,然后再调用。
通常用于结构体的默认输出,例如:

type Student struct {	number int 	realname string	age int}func main() {	stu := &Student{		number: 1,		realname: "王小明",		age: 18,	}	fmt.Println(stu)}复制代码
&{1 王小明 18}复制代码

改成:

type Student struct {	number int 	realname string	age int}func (t *Student) String() string {	return fmt.Sprintf("学号: %d\n真实姓名: %s\n年龄: %d\n", t.number, t.realname, t.age)}func main() {	stu := &Student{		number: 1,		realname: "王小明",		age: 18,	}	fmt.Println(stu)}复制代码
学号: 1真实姓名: 王小明年龄: 18复制代码

瞬间感觉高大上了吧!!

Error


type TestError struct {}func (t TestError) Error() string {	return "我是Error"}func main() {    fmt.Println(TestString{})}复制代码
我是Error复制代码

实际上使用方式跟String()一样,但是设计代码时不能互相替换实现。

最常用的用法是独立封装type XXXError struct{},在文章最尾会揣摸一下为什么要这样用。

Format

type TestFormat struct {}func (t TestFormat) Format(s fmt.State, c rune) {	switch c {	case 'c':		switch {		case s.Flag('+'):			fmt.Printf("我是+c\n")		default:			fmt.Fprint(s, "我是c\n")		}	default:		fmt.Print("我是Format")	}}func main() {    t := TestFormat{}    fmt.Println(t)    fmt.Printf("%c\n", t)    fmt.Printf("%+c\n", t)    fmt.Printf("%s\n", t)}复制代码
我是Format我是c我是+c我是Format复制代码

fmt.Println也会调用Format的接口,所以String() Format()不能同一个结构体里面。 通常使用跟Error()类似,可以参考一下里的stack.gofunc (f Frame) Format(s fmt.State, verb rune)

GoString

type TestGoString struct {}func (t TestGoString) GoString() string {	return "我是GoString"}func main() {    t := TestGoString{}    fmt.Println(TestGoString{})    fmt.Printf("%s %#v\n", t, t)}复制代码
{}{} 我是GoString复制代码

如上所示fmt.Println并没调用GoString方法,只能通过格式化%#+标记输出。

在没有实现接口的情况下,通常用来输出默认相应值,如下:

func main() {	var i uint = 18	// 输出十六进制	fmt.Printf("%x\n", i)	fmt.Printf("%#x\n", i)}复制代码
120x12复制代码

注意事项

fmt/print.gopp.handleMethods(verb rune) (handled bool)

func (p *pp) handleMethods(verb rune) (handled bool) {	...	// 判断Formatter	if formatter, ok := p.arg.(Formatter); ok {	    ...	    formatter.Format(p, verb)	    return	}            // 判断是否含有#标识符	if p.fmt.sharpV {	        // 判断GoStriner		if stringer, ok := p.arg.(GoStringer); ok {                        ...			p.fmt.fmtS(stringer.GoString())			return		}	} else {		switch verb {		case 'v', 's', 'x', 'X', 'q':			switch v := p.arg.(type) {			// 符合error接口			case error:                                ...				p.fmtString(v.Error(), verb)				return                        // 符合Stringer接口			case Stringer:                                ...				p.fmtString(v.String(), verb)				return			}		}	}	return false}复制代码

Format -> (#)GoString -> ((v,s,x,X,q)Error -> String) 源码四个接口都在handlerMethods方法调用控制,都不是互相独立,根据优先顺序调用。所以接口的设计,尽可能独立封装,避免混淆。

小结

String() 用于对结构体的标准输出等。

Error() 封装error的方法,可以改一些错误上传到日志系统或者打印Stack。
Format() 对于String()的高级用法,用于多种类型或者格式使用。
GoString() 常用于相对值。


欢迎大神们交流,指导!

转载于:https://juejin.im/post/5c396a396fb9a049f66c564a

你可能感兴趣的文章
python学习笔记4-数据类型-数字
查看>>
nagios监控check_mysql报错:libmysqlclient.so.18: cannot open shared object file
查看>>
系统架构随笔 - 设计好每一款应用
查看>>
安装mysql过程
查看>>
/etc/profile和/etc/skel
查看>>
useradd命令中的-d参数不好用
查看>>
UIScrollView、UIPageControl的练习
查看>>
使用SHA-1摘要算法和证书链签名的软件包将不再被接受
查看>>
除百度、Google外其他蜘蛛IP封锁脚本
查看>>
迅雷面试行
查看>>
戴尔EqualLogic主机软件:新意何在?为何值得我关注?
查看>>
自制应用层协议的编写
查看>>
Python - 关于Python的变量
查看>>
解决exp无法导出问题
查看>>
XML(eXtensible Markup Language)速成
查看>>
自建框架-mf
查看>>
Unix删除文件的找回方法
查看>>
java中的匿名内部类总结
查看>>
maven 使用filter动态处理资源文件变量
查看>>
linux 环境下使用信号量实现司机售票员进程同步,线程同步问题
查看>>