douluhaikao93943 2018-08-28 15:19
浏览 124
已采纳

接口的golang地址和接口的区别

I have found many similar problem, but not what I want please see following codes.

(1)

var buf bytes.Buffer
fmt.Fprint(&buf,"test")

(2)

var w http.ResponseWriter
http.Error(w,http.StatusText(http.StatusBadRequest),http.StatusBadRequest)

both http.ResponseWriter and bytes.Buffer implement io.Writer interface, so I think they should have same behavior.

when I change to

http.Error(&w,http.StatusText(http.StatusBadRequest),http.StatusBadRequest)

jetbrains goland tell me

Cannot use '&w' (type *http.ResponseWriter) as type ResponseWriter

I wonder why buf have '&' can works, but another don't work?

I googled, somebody say when pass value to function, it can reference to &w

but another say if you pass a pointer, it can deference to value

from https://github.com/golang/go/wiki/MethodSets#variables

To make it easier to remember these rules, it may be helpful to simply consider the pointer- and value-receiver methods separately from the method set. It is legal to call a pointer-valued method on anything that is already a pointer or whose address can be taken (as is the case in the above example). It is legal to call a value method on anything which is a value or whose value can be dereferenced (as is the case with any pointer; this case is specified explicitly in the spec).

I am totally confused, I can't understand by myself. I wish you can help me, thank you!

  • 写回答

1条回答 默认 最新

  • dpwbc42604 2018-08-28 21:19
    关注

    Maybe I can try to explain more detailed what all the very good comments are already saying:

    Interfaces are (mostly) pointers in go

    Interfaces in go are implemented (satisfied) if another type implements all the methods an interface defines. Usually that is done by adding the methods on the pointer of the type, not the type directly.

    type SomeInterface interface {
        SomeMethod string
    }
    
    type SomeStruct struct {} // often is a struct but does not have to be
    
    // a method on the structs pointer
    func (s *SomeStruct) SomeMethod string {
        return ""
    }
    

    The results of this:

    1. SomeStruct does NOT implement SomeInterface, *SomeStruct does!
    2. An Interface is (usually) already a pointer.

    Your example

    var b bytes.Buffer
    fmt.Fprintf(&b, "some text")
    
    var w http.ResponseWriter
    http.Error(w, "some error", 1)
    

    Variable b of type bytes.Buffer is a struct as you can see from the source code:

    type Buffer struct {
        buf       []byte   // contents are the bytes buf[off : len(buf)]
        off       int      // read at &buf[off], write at &buf[len(buf)]
        bootstrap [64]byte // memory to hold first slice; helps small buffers avoid allocation.
        lastRead  readOp   // last read operation, so that Unread* can work correctly.
    
        // FIXME: it would be advisable to align Buffer to cachelines to avoid false
        // sharing.
    }
    

    If you want to use it as type io.Writer (interface) you need to get a pointer of bytes.Buffer as (usually) pointer methods are used in go: fmt.Fprintf(&b, "some text")

    Variable w of type http.ResponseWriter is an interface:

    type ResponseWriter interface {
        Header() Header
        Write([]byte) (int, error)
        WriteHeader(statusCode int)
    }
    

    Since interfaces are (usually) already pointers to some underlying implementation we can use it without taking a pointer: http.Error(w, "some error", 1).

    Interface initialisation

    An interface itself cannot be initialised and used! You always need a struct or other type to implement the interface and then you can initialise that and use it as type SomeInterface. For example here is the implementation of gin for a http.ResponseWriter. As you can see from the code it uses pointer receivers for its methods. So http.ResponseWriter is already a pointer to a struct.

    Disclaimer

    This is just one way of trying to make this complex topic sound simple (hopefully). This is not a technically complete or completely accurate explanation. Trying to stay simple and yet as accurate as possible.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥20 idea运行测试代码报错问题
  • ¥15 网络监控:网络故障告警通知
  • ¥15 django项目运行报编码错误
  • ¥15 请问这个是什么意思?
  • ¥15 STM32驱动继电器
  • ¥15 Windows server update services
  • ¥15 关于#c语言#的问题:我现在在做一个墨水屏设计,2.9英寸的小屏怎么换4.2英寸大屏
  • ¥15 模糊pid与pid仿真结果几乎一样
  • ¥15 java的GUI的运用
  • ¥15 我想付费需要AKM公司DSP开发资料及相关开发。