Introduction to the

Golang’s interface is so widely used that it is used in almost every package, with the FMT package being one of the most used. In real development, you define the standard output of a structure with String(), Error(), Format(), and, more specifically, GoString(). The following describes how the interface is used, how it is used, and where to pay attention.

String()

type TestString struct {}
func (t TestString) String(a) string {
	return "I am a String"
}
func main(a) {
    fmt.Println(TestString{})
}
Copy the code
I am a StringCopy the code

It’s relatively simple to use, as long as the structure has String() String can be printed. The FMT package will determine whether there is a FMT.Stringer interface, and then call. Usually used for default output of a structure, for example:

type Student struct {
	number int
 	realname string
	age int
}
func main(a) {
	stu := &Student{
		number: 1,
		realname: "Wang Xiaoming",
		age: 18,
	}
	fmt.Println(stu)
}
Copy the code
&{1 Wang Xiaoming 18}Copy the code

To:

type Student struct {
	number int
 	realname string
	age int
}
func (t *Student) String(a) string {
	return fmt.Sprintf("Student ID: %d\n Real Name: %s\n Age: %d\n", t.number, t.realname, t.age)
}
func main(a) {
	stu := &Student{
		number: 1,
		realname: "Wang Xiaoming",
		age: 18,
	}
	fmt.Println(stu)
}
Copy the code
Student ID: 1 Real Name: Wang Xiaoming Age: 18Copy the code

Instantly feel high up bar!!

Error


type TestError struct {}
func (t TestError) Error(a) string {
	return "I am the Error"
}
func main(a) {
    fmt.Println(TestString{})
}
Copy the code
I am the ErrorCopy the code

It is actually used the same way as String(), but cannot be implemented interchangeably when designing the code. The most common use is to wrap type XXXError struct{} separately, which I’ll explore at the end of this article.

Format

type TestFormat struct {}
func (t TestFormat) Format(s fmt.State, c rune) {
	switch c {
	case 'c':
		switch {
		case s.Flag('+'):
			fmt.Printf("I am + c \ n")
		default:
			fmt.Fprint(s, "I am c \ n")}default:
		fmt.Print("I am the Format")}}func main(a) {
    t := TestFormat{}
    fmt.Println(t)
    fmt.Printf("%c\n", t)
    fmt.Printf("%+c\n", t)
    fmt.Printf("%s\n", t)
}
Copy the code
I'm Format and I'm c and I'm + C and I'm FormatCopy the code

Fmt.println also calls the Format interface, so String() Format() cannot be in the same structure. Func (f Frame) Format(s FMT.State, verb rune) : func (f Frame) Format(s fmt.state, verb rune)

GoString

type TestGoString struct {}
func (t TestGoString) GoString(a) string {
	return "I am GoString"
}
func main(a) {
    t := TestGoString{}
    fmt.Println(TestGoString{})
    fmt.Printf("%s %#v\n", t, t)
}
Copy the code
{} {} I'm GoStringCopy the code

As shown above, fmt.println does not call the GoString method and can only be printed by formatting the %#+ flag. When no interface is implemented, it is usually used to print the corresponding default value, as follows:

func main(a) {
	var i uint = 18
	// Output hexadecimal
	fmt.Printf("%x\n", i)
	fmt.Printf("%#x\n", i)
}
Copy the code
12
0x12
Copy the code

Matters needing attention

FMT /print.go pp. HandleMethods (verb rune) (Handled bool)

func (p *pp) handleMethods(verb rune) (handled bool){.../ / determine the Formatter
	if formatter, ok := p.arg.(Formatter); ok {
	    ...
	    formatter.Format(p, verb)
	    return
	}
    
        // Check if there is a # identifier
	if p.fmt.sharpV {
	        / / determine 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) {
			// Conforms to the error interface
			case error:
                                ...
				p.fmtString(v.Error(), verb)
				return
                        // Stringer interface
			case Stringer:
                                ...
				p.fmtString(v.String(), verb)
				return}}}return false
}

Copy the code

Format -> (#)GoString -> (v,s,x, x, q)Error -> String) Therefore, the interface design, as far as possible independent packaging, to avoid confusion.

summary

String() is used for standard output to structures, etc. Error() encapsulates the Error method and can change some errors to upload to the log system or print Stack. Format() An advanced use of String() for multiple types or formats. GoString() is often used for relative values.


Welcome the gods to exchange, guidance!