Why does code inside unused method run? - go

The code below comes from Todd Mcleod's Golang web-dev course. What I fail to understand - even watching his video's over and over and googling everything about methods- is the following: The method ServeHTTP is attached to type hotdog, but is never ran. Still the code inside the method (in this case Fprintln(...) is executed. (When you run this code and go to localhost:8080, it diesplays "Any code you want in this func".) Could anyone explain me why this is?
Thanks a lot!
package main
import (
"fmt"
"net/http"
)
type hotdog int
func (m hotdog) ServeHTTP(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Any code you want in this func")
}
func main() {
var d hotdog
http.ListenAndServe(":8080", d)
}

It is run. ListenAndServe calls it for every request made to your server.

this function is run when the type hotdog is used
func (m hotdog) ServeHTTP(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Any code you want in this func")
}
in the main you create variable d with the type hotdog,
then in the ListenAndServe and you tell your code to use variable d every time someone connects to your server and because d is of type hotdog your first function is run everytime someone connects
func main() {
var d hotdog
http.ListenAndServe(":8080", d)
}

Since you passed hotdog, which implements ServeHTTP, as a handler, every request received will be sent to hotdog's ServeHTTP.

Related

GO Lang Web Application- Auto Compile and Reload [duplicate]

This question already has answers here:
Go Auto-Recompile and Reload Server on file change
(12 answers)
Closed 2 years ago.
Created basic web app and it is running on localhost:8080, I have to restart the server on each file change.
File changes take affect Ctrl +c (terminate program)and run again go program go run hello.go.
We do not want to terminate program of each file changes. If we do any changes and refresh browser new change take affect like PHP language
EX
First Program
package main
import (
"fmt"
"net/http"
)
func helloWorld(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello World")
}
func main() {
http.HandleFunc("/", helloWorld)
http.ListenAndServe(":8080", nil)
}
Second Program
package main
import (
"fmt"
"net/http"
)
func helloWorld(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Happy Coding")
}
func main() {
http.HandleFunc("/", helloWorld)
http.ListenAndServe(":8080", nil)
}
Anyone have a solution to this?
You have to understand that Go & PHP are not the same at all. Go is a statically-typed, COMPILED language -- where PHP is a dynamically-typed, INTERPRETED language.
So using some special third party solution like the one mentioned in the comment above by #AyushGupta is probably your best bet. What you described in your question is the workflow when building services with Go. You compile a binary, run it & repeat when you make changes.

How does http.HandlerFunc get a response writer & request without being explicitly passed one?

I'm learning Go coming from a PHP/JS background. I came across an example where I'm not quite sure what's happening. How is timeHandler receiving the http.ResponseWriter & http.Request if they are not explicitly passed in to the function call?
package main
import (
"log"
"net/http"
"time"
)
func timeHandler(w http.ResponseWriter, r *http.Request) {
tm := time.Now().Format(time.RFC1123)
w.Write([]byte("The time is: " + tm))
}
func main() {
mux := http.NewServeMux()
// *** Why isn't there any undefined value errors here?
th := http.HandlerFunc(timeHandler)
mux.Handle("/time", th)
http.ListenAndServe(":8080", mux)
}
The related post did not answer the question in layman enough terms. The thread in this post with Deefdragon did a good job. To summarize:
it registers the function, without calling it until later
In go, functions are first class, meaning they can be assigned to variables, passed into functions etc.
In this case, http.HandlerFunc accepts as an argument a function (with parameters a writer and request), creating a handler th. th is then passed to the mux.
When a request is made to the time endpoint, the mux looks for the proper handler, th. It then executes th. (sometimes called a callback)
Inside th, the callback to the handler function is then made, passing the arguments w and r. This then executes the code in your example
By the source code from the documentation
func HandleFunc(pattern string, handler func(ResponseWriter, *Request))
As you can see it passes a function that must have a specific signature. It's not invoking anything it's simply using a pointer to it. The function will then be invoked by the package. So in order for the package to invoke it must know what signature to call.
You could think it like an interface. It's simply the declaration, the implementation is a different thing. The argument are passed automaticly by the http package when someone goes to your url.

Reference to undefined identifier bytes.ReplaceAll

I am trying to build a simple webserver. I want to replace all \n with <br>.
I wanted to use bytes for this, because my page body is stored as an []byte.
I use bytes.ReplaceAll() for this. But it keeps saying that it's a reference to undefined identifier.
Can someone tell me why? I tried the exact same line within an online Compiler and it worked just fine. Do I miss the library?
See my code below:
import (
"bytes"
"html/template"
"io/ioutil"
"log"
"net/http"
"regexp"
)
type Page struct {
Title string
Body []byte
}
func editHandler(w http.ResponseWriter, r *http.Request, title string) {
p, err := loadPage(title)
if err != nil {
p = &Page{Title: title}
}
// THE LINE THAT CAUSES TROUBLE
p.Body = bytes.ReplaceAll(p.Body, []byte("\n"), []byte("<br>"))
renderTemplate(w, "edit", p)
}
The bytes package is part of the standard library, so it is unlikely that you don't have it if you have the go tool available to you.
But do note that bytes.ReplaceAll() was added in Go 1.12, so if you have an older Go SDK, this function will not be available to you.
Execute go version to find out. Get the latest Go from the official site: https://golang.org/dl/
Further to icza's answer,
For the benefit of Go versions prior to 1.12, the following are equivalent:
bytes.ReplaceAll(a, b, c)
and
bytes.Replace(a, b, c, -1)
See the implementation of ReplaceAll

Get Receiver Type and Method name from just a reference of function in Go

Given a code setup like this,
package main
import (
"fmt"
"reflect"
"runtime/debug"
)
type A struct{}
func (o *A) B() error {
debug.PrintStack()
return nil
}
func main() {
a := &A{}
b := a.B
// Note that if run b(), it can print the stack and show the info
// "(*A).B-fm" and "(*A).B"
m := reflect.ValueOf(b)
fmt.Println(m.Type().String())
}
Is it possible to get the information of b's receiver type A and B as a method? How if possible?
Note that b is value of method B of type A.
(Possible use scenario, generating a constant unique API ID based on only a reference like b, by forming a string like (*A).B. It's used to build a debug tool without a need to change existing code.)
update:
This will do the work.
fmt.Println(runtime.FuncForPC(m.Pointer()).Name())
Credits to this awesome article,

How HandlerFunc(f) convert a function to an interface type?

When check following code, got a doubt with type convert from function to interface.
Code
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()
}
The above code works.
(Then I tried to write a small program to check is this a general feature, but it won't work, check following code)
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()
}
Output:
./func_to_intf.go:30:14: cannot use fa (type AdderFunc) as type Adder
in argument to doAdd: AdderFunc does not implement Adder (missing add
method)
Questions
http.HandlerFunc(helloHandler) get a value of type http.Handler, since that's what http.Handle() expect, is that correct?
If yes, then means it convert a function into a value of an interface type, how did that happen?
Is this a built-in feature of go?
I did a test (as in func_to_intf.go above), and seems not.
Or, is http.HandlerFunc's special implementation achieve that?
#Update - Summary
(Though the answer(s) addressed the questions pretty well, but after reviewing & more testing, there are several other go features required to totally erase the original doubt, as following.)
Function type.
Function is value, and it has type.
Function type could be defined via type keyword on a function signature.
e.g type AdderFunc func(int, int) int
Type convertor T(v) on function.
Any function could be converted to a function type with the same signature, just via T(v), use function type name as T, and actual function as v.
Then when the new value is called, the actual function v is called.
e.g fa := AdderFunc(simpleAdd)
(this is blur to me before asking the question, and that's one of the main reason I was confused).
It is a simple type-conversion.
In Go you can define custom type besides structs. In this case, http.HandlerFunc is a function type, func(http.ResponseWriter,*http.Request). Since your function is of the same underlying type (signature) as the custom type, it can be converted to it.
Furthermore, code can define methods on custom type, no matter what underlying type it is, or whether it is a struct or not. In this case, http package defines ServeHTTP method on it, and of course, it just calls the function itself.
You can read the source code here: https://golang.org/src/net/http/server.go?s=58384:58444#L1936
As for the adder in your sample code, you can do the same: Define a method on AdderFunc.
func (a AdderFunc) add(x, y int) int {
return a(x, y)
}
Playground: https://play.golang.org/p/5mf_afHLQA2
http.HandlerFunc is a type that satisfy interface http.Handler by providing method http.ServeHTTP(ResponseWriter, *Request).
http.HandlerFunc(helloHandler) is a type conversion which convert types with same underlying base type but different method set.
You example working
Not special or built-in feature. Instead http.HandlerFunc is a type that implements the http.Handler interface. Have a look at its implementation which is quite nifty https://github.com/golang/go/blob/d3c3aaa61f7598f275f30fabd3749379fe0f2720/src/net/http/server.go#L1956
As the docs say:
The HandlerFunc type is an adapter to allow the use of ordinary functions as HTTP handlers. If f is a function with the appropriate signature, HandlerFunc(f) is a Handler that calls f.
So, it's not a function, but a wrapper type, declared as:
type HandlerFunc func(ResponseWriter, *Request)
But Go allows (and that's one of its greatest features, in my opinion) to make any newly declared type implement any possible interface just by defining the require method. So the type HandlerFunc implements the interface Handler by defining the method ServeHttp. The implementation just calls the wrapped function.

Resources