在检查以下代码时,对于将类型从函数转换为接口存在疑问。
http_hello.go:
package main
import (
"fmt"
"log"
"net/http"
)
// hello http,
func helloHttp() {
// register handler,
http.Handle("/", http.HandlerFunc(helloHandler))
// start server,
err := http.ListenAndServe(":9090", nil)
if err != nil {
log.Fatal("ListenAndServe:", err)
}
}
// handler function - hello,
func helloHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, you've requested: %s\n", r.URL.Path)
}
func main() {
helloHttp()
}
上面的代码有效。
(然后,我尝试编写一个小程序来检查这是否是一项常规功能,但无法正常工作,请检查以下代码)
func_to_intf.go:
package main
import (
"fmt"
)
// an interface,
type Adder interface {
add(a, b int) int
}
// alias of a function signature,
type AdderFunc func(int, int) int
// a simple add function,
func simpleAdd(a, b int) int {
return a + b
}
// call Adder interface to perform add,
func doAdd(a, b int, f Adder) int {
return f.add(a, b)
}
func funcToIntf() {
fa := AdderFunc(simpleAdd)
fmt.Printf("%#v, type: %T\n", fa, fa)
a, b := 1, 2
sum := doAdd(a, b, fa)
fmt.Printf("%d + %d = %d\n", a, b, sum)
}
func main() {
funcToIntf()
}
输出:
./ func_to_intf.go:30:14:不能将fa(类型AdderFunc)用作类型Adder 在doAdd的参数中:AdderFunc不实现Adder(缺少add 方法)
http.HandlerFunc(helloHandler)
获得类型为http.Handler
的值,因为正是http.Handle()
所期望的,这是正确的吗?func_to_intf.go
一样),看来没有。http.HandlerFunc
的特殊实现是否可以实现?(尽管答案很好地解决了这些问题,但是在经过反复审查和更多测试之后,还需要其他一些go功能来完全消除最初的疑问,如下所述。) >
type
关键字定义功能类型。type AdderFunc func(int, int) int
T(v)
。T(v)
,任何函数都可以转换为具有相同签名的函数类型,将函数类型名称用作T
,将实际函数用作v
。v
。fa := AdderFunc(simpleAdd)
答案 0 :(得分:2)
这是一个简单的类型转换。
在Go语言中,您可以定义struct
之外的自定义类型。在这种情况下,http.HandlerFunc
是函数类型func(http.ResponseWriter,*http.Request)
。由于您的函数与自定义类型具有相同的基础类型(签名),因此可以将其转换为它。
此外,代码可以定义自定义类型的方法,无论它是什么基础类型,或者它是否为struct
。在这种情况下,http
包在其上定义了ServeHTTP
方法,当然,它只是调用函数本身。
您可以在此处阅读源代码:https://golang.org/src/net/http/server.go?s=58384:58444#L1936
对于示例代码中的加法器,您可以执行以下操作:在AdderFunc
上定义一个方法。
func (a AdderFunc) add(x, y int) int {
return a(x, y)
}
答案 1 :(得分:1)
不是特殊功能或内置功能。相反,http.HandlerFunc
是实现http.Handler
接口的类型。看看它的实现是多么漂亮https://github.com/golang/go/blob/d3c3aaa61f7598f275f30fabd3749379fe0f2720/src/net/http/server.go#L1956
答案 2 :(得分:1)
docs说:
HandlerFunc类型是一个适配器,允许将普通函数用作HTTP处理程序。如果f是具有适当签名的函数,则HandlerFunc(f)是调用f的处理程序。
所以,它不是一个函数,而是一个包装器类型,声明为:
final VideoView videoView=findViewById(R.id.videoView);
videoView.setVideoURI(Uri.parse("android.resource://"+getPackageName()+"/"+R.raw.video));
final MediaController mediaController=new MediaController(this);
videoView.setMediaController(mediaController);
final TextView textView = findViewById(R.id.textView);
textView.setText("0");
int topContainerId = getResources().getIdentifier("mediacontroller_progress","id", "android");
final SeekBar seekbar = (SeekBar) mediaController.findViewById(topContainerId);
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
int currentValue = Integer.parseInt(textView.getText().toString());
int newValue = progress / 1000;
if (newValue != currentValue) {
textView.setText(String.valueOf(newValue));
}
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
videoView.start();
但是Go允许(我认为这是它最大的功能之一),只需定义require方法,就可以使任何新声明的类型实现任何可能的接口。因此,类型type HandlerFunc func(ResponseWriter, *Request)
通过定义方法ServeHttp
来实现接口HandlerFunc
。该实现只调用包装的函数。
答案 3 :(得分:1)
http.HandlerFunc
是通过提供方法http.Handler
满足接口http.ServeHTTP(ResponseWriter, *Request)
的类型。
http.HandlerFunc(helloHandler)
是类型转换,用于转换具有相同基础基本类型但方法集不同的类型。
您以working
为例