在Golang中,可以通过子类化和重新定义方法来实现吗?

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

Can I subclass and redefine a method in Golang?

问题

我正在使用一个Github客户端,它使我能够更轻松地调用Github API方法。

这个库允许我在初始化时提供自己的*http.Client

httpClient := &http.Client{}
githubClient := github.NewClient(httpClient)

这样做很好,但现在我需要做一些其他的事情。我想自定义客户端,以便每个请求(即Do方法)都会添加一个自定义的头部。

我已经阅读了一些关于嵌入的内容,目前我尝试的是这样的:

package trackerapi

import (
	"net/http"
)

type MyClient struct {
	*http.Client
}

func (my *MyClient) Do(req *http.Request) (*http.Response, error) {
	req.Header.Set("cache-control", "max-stale=3600")
	return my.Client.Do(req)
}

但编译器不允许我在默认的客户端位置使用我的自定义MyClient

httpClient := &trackerapi.MyClient{}

// 错误:无法将httpClient(类型为*MyClient)作为类型*http.Client使用。
githubClient := github.NewClient(httpClient)

我是一个相对新手的Golang开发者,所以我的问题是:这样做是正确的吗?如果不是,有什么推荐的方法?

英文:

I'm using a Github Client that allows me to call github API methods more easily.

This library allows me to provide my own *http.Client when I initialize it:

httpClient := &http.Client{}
githubClient := github.NewClient(httpClient)

It works fine but now I need something else. I want to customize the Client so that every request (i.e. the Do method) gets a custom header added.

I've read a bit about embedding and this is what I've tried so far:

package trackerapi

import(
    "net/http"
)

type MyClient struct{
    *http.Client
}

func (my *MyClient)Do(req *http.Request) (*http.Response, error){

    req.Header.Set("cache-control","max-stale=3600")

    return my.Client.Do(req)

}

But the compiler does not let me use my custom MyClient in place of the default one:

httpClient := &trackerapi.MyClient{}

// ERROR: Cannot use httpClient (type *MyClient) as type 
//*http.Client. 
githubClient := github.NewClient(httpClient)

I'm a bit of a golang newbie so my question is: Is this the right way to do what I want to and, if not, what's the recommended approach?

答案1

得分: 6

可以在Golang中创建子类吗?

简短回答:不可以。Go语言不是面向对象的,因此没有类,因此无法进行子类化。

更详细的回答:

你对嵌入的理解是正确的,但是你无法将自定义的客户端替换为期望*http.Client的任何东西。这就是Go接口的用途。但是标准库在这里没有使用接口(对于某些情况,它会使用接口,当有意义时)。

另一个可能的方法(根据具体需求而定)是使用自定义的传输方式,而不是自定义的客户端。这确实使用了接口。你可以使用自定义的RounTripper,添加必要的头信息,并将其分配给*http.Client结构体。

英文:

> Can I subclass ... in Golang?

Short answer: No. Go is not object oriented, therefore it has no classes, therefore subclassing is categorically an impossibility.

Longer answer:

You're on the right track with embedding, but you won't be able to substitute your custom client for anything that expects an *http.Client. This is what Go interfaces are for. But the standard library doesn't use an interface here (it does for some things, where it makes sense).

Another possible approach which may, depending on exact needs, work, is to use a custom transport, rather than a custom client. This does use an interface. You may be able to use a custom RoundTripper that adds the necessary headers, and this you can assign to an *http.Client struct.

huangapple
  • 本文由 发表于 2017年4月3日 04:10:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/43173041.html
匿名

发表评论

匿名网友

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

确定