Why does switch match a different type in below code sample in golang

huangapple go评论92阅读模式
英文:

Why does switch match a different type in below code sample in golang

问题

链接:
https://play.golang.org/p/69I8PAuoAV

提取:

package main

import "fmt"

type Stringer interface {
    String() string
}

type fakeString struct {
    content string
}

// 用于实现Stringer接口的函数
func (s *fakeString) String() string {
    return s.content
}

func printString(value interface{}) {
    switch str := value.(type) {
    case string:
        fmt.Println(str)
    case Stringer:
        fmt.Println(str.String())
    }
}

func main() {
    s := &fakeString{"Ceci n'est pas un string"}
    printString(s)
    printString("Hello, Gophers")
}

当调用printString(s)函数时,它匹配到了case Stringer部分。
s的类型是*fakeString而不是Stringer
为什么它匹配到了Stringer

我使用了fmt.Println(reflect.TypeOf(str)),它确认了类型为*main.fakeString

英文:

Link:
https://play.golang.org/p/69I8PAuoAV

Extract:

package main

import "fmt"

type Stringer interface {
	String() string
}

type fakeString struct {
	content string
}

// function used to implement the Stringer interface
func (s *fakeString) String() string {
	return s.content
}

func printString(value interface{}) {
	switch str := value.(type) {
	case string:
		fmt.Println(str)
	case Stringer:
		fmt.Println(str.String())
	}
}

func main() {
	s := &fakeString{"Ceci n'est pas un string"}
	printString(s)
	printString("Hello, Gophers")

}

The printString(s) function call when reaching case matches the case Stringer part.
s is of type *fakeString not Stringer.
Why does it match Stringer.

I did a fmt.Println(reflect.TypeOf(str)) and it confirmed the type as *main.fakeString

答案1

得分: 4

在Go语言中,要满足一个接口,你只需要实现该接口的方法,没有其他要求。在这个例子中,为了具有Stringer的行为,你需要实现String() string方法,因此类型fakeString表现得像一个Stringer,因为它实现了该方法;从面向对象编程的角度来看,我们使用接口只是为了定义行为,而不是类型或值。所以你可能在不知情的情况下整天都在实现Go接口,但这并不重要,只有在需要满足特定行为时才会有影响。

实际上,在一个真实的项目中,你可能希望在printString方法的switch语句中添加一个default情况,以便检测接口{}是其他类型的情况,像这样:

func printString(value interface{}) {
    switch str := value.(type) {
    case string:
        fmt.Println("string", str)
    case Stringer:
        fmt.Println("Stringer", str.String())
    default:
        fmt.Printf("unexpected type: %T value: '%v'", str, str)
    }
}

// main:
printString(2)

链接:https://play.golang.org/p/pmxSXfUu4e

英文:

In Go to satisfy an interface all you have to do is implement the methods of that interface nothing else. In this case to have a behavior as a Stringer you have to implement String() string, so the type fakeString behaves as a Stringer because implement that method; in terms of OOP we use interfaces just to define behavior not types or values. So you may be implementing Go interfaces all day without knowing, but not big deal, it only matters when you have to satisfy behaviors.

Actually in a real project you may want to add a default case to your switch in the method printString, to detect when the interface{} is something else, like this:

func printString(value interface{}) {
	switch str := value.(type) {
	case string:
		fmt.Println("string", str)
	case Stringer:
		fmt.Println("Stringer", str.String())
	default:
		fmt.Printf("unexpected type: %T value: '%v'", str, str)
	}
}

// main:
printString(2)

https://play.golang.org/p/pmxSXfUu4e

答案2

得分: 1

这是关于golang中的接口满足性

在golang中有两种类型:接口类型具体类型

  • 具体类型switch语句中的行为与你期望的完全一致:变量是给定类型的实例。
  • 另一方面,接口类型的行为不同,它检查变量是否满足接口的要求。

嗯,满足?它是如何工作的呢?

> 如果(具体)类型拥有接口所需的所有方法,则该类型满足该接口。
>
> -- golang编程语言

在这种情况下,Stringer是一个接口,只声明了一个方法:String() string。而fakeString通过拥有自己的String() string方法来满足它。

然而需要注意两点:

  1. 具体类型可以有许多其他方法,只要它拥有接口中声明的所有方法,它仍然满足该接口。
  2. 方法的顺序无关紧要,重要的是方法的集合。
英文:

This is interface satisfaction in golang.

There are two kinds of type in golang: interface type and concrete type.

  • concrete type works exactly as you expected in switch: the variable is an instance of the given type
  • interface type on the other hand works differently, it checks if the variable satisfies the interface.

Hum, safisfies? How does it work?

> A (concrete) type satisfies an interface if it possesses all the methods the interface requires.
>
> -- the golang programming language

In the case, Stringer is an interface, declaring only one method: String() string. And fakeString satisfies it by having its own String() string method.

Two things to note however:

  1. concrete type can have many other methods, it still satisfies the interface if it possesses all methods declared in interface
  2. the methods order does not matter, all that matters is the set of methods.

huangapple
  • 本文由 发表于 2016年11月20日 17:35:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/40702527.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定