I'm using GoLand IDE and I'm getting a problem when running my Go web app. The code isn't compiling when the Terminal is used.
Here is the problem: The terminal duplicated the command prompt when I make an attempt at running the code.
C:\Users\Evan\go\src\awesomeProject9>go run main.go
C:\Users\Evan\go\src\awesomeProject9>
package main
import (
"fmt"
"html/template"
"net/http"
)
var tpl *template.Template
func init(){
template.Must(template.ParseGlob("templates/*.html"))
}
func main() {
http.HandleFunc("templates/index", idx)
http.ListenAndServe("8000", nil)
fmt.Println("hello World")
}
func idx(w http.ResponseWriter, r *http.Request){
tpl.ExecuteTemplate(w, "templates/index.html", nil)
}
Thanks to #zerkms for pointing out, that I was wrong. I simply ran into the exact mistake I tried to warn you later on:
you really should use the err returned by called functions, since these really help you a lot! For startes simply:
err := http.ListenAndServe("8000", nil)
if err != nil {
log.Fatal(err)
}
This panics with:
2018/12/18 10:43:16 listen tcp: address 8000: missing port in address
the correct line should be
err := http.ListenAndServe(":8000", nil)
WRONG only for documentation
ListenAndServe doesn't block the further code execution....
Related
I am using the atom IDE, and for some reason whenever I add this to my imports:
"github.com/nlopes/slack"
And save the file, it removes the import. So I'm not sure why but it isn't finding the InteractionCallback type in the library?
I copied this code from the example:
func unmarshalSuggestionCallback(j string) (*InteractionCallback, error) {
callback := &InteractionCallback{}
if err := json.Unmarshal([]byte(j), &callback); err != nil {
return nil, err
}
return callback, nil
}
I am getting this error:
undefined: InteractionCallback
How can I tell if my library I just downloaded has the type defined? Or am I referencing the type incorrectly?
Please use this command in your terminal:
go get -u github.com/nlopes/slack
After that try to run this code:
package main
import (
"encoding/json"
"fmt"
"github.com/nlopes/slack"
)
func unmarshalSuggestionCallback(j string) (*slack.InteractionCallback, error) {
callback := &slack.InteractionCallback{}
if err := json.Unmarshal([]byte(j), &callback); err != nil {
return nil, err
}
return callback, nil
}
func main() {
callback,_:=unmarshalSuggestionCallback(`{"type":"callback"}`)
fmt.Println(callback.Type)
}
Everything should work fine, I have checked in my PC
You need to specify from which package InteractionCallback comes from, in your case its slack package - slack.InteractionCallback
Note: Newbie for golang language
Here is the sample program hello.go I wrote to check the behavior and I am seeing the issue where I don't see anything being written by Logger in any functions other than init().
package main
import (
"fmt"
"os"
"io"
"log"
)
var (
testLogger *log.Logger
)
func init() {
test_log := "/tmp/t1.log"
fmt.Printf("Logs are saved to %v\n", test_log)
f, err := os.OpenFile(test_log, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0600)
if err != nil {
fmt.Printf("ERROR Can't create log file! Reason: %v \n", err)
os.Exit(1)
}
defer f.Close()
multiWriter := io.MultiWriter(f)
testLogger = log.New(multiWriter, "", log.Ldate|log.Ltime|log.Lshortfile)
testLogger.Printf("in init..")
}
func main() {
pretest()
test()
testLogger.Printf("Back to main ... ")
}
func pretest() {
testLogger.Printf("In pretest ... ")
}
func test() {
testLogger.Printf("in test..")
}
Here is the output and content of the file being written to:
➜ ./hello
Logs are saved to /tmp/t1.log
➜ cat /tmp/t1.log
2018/06/28 11:23:25 hello.go:27: in init..
AFAIK, The testLogger being shared in the same package should be accessible by each function and able to being used. Please correct me if my understanding is wrong? Am I missing anything in the code? Please provide any pointer or reference on this issue? Thanks.
defer f.Close()
You are doing that defer in the init function, meaning that the file will be closed as soon as the init function finishes.
Since the init function runs before main, the file will be closed already when you try to write from all your other functions.
Move that defer to the main function so that it is closed when your program exits.
Note that in this specific case, you don't even need to close the os.File since by default File has a finalizer to close itself when it is collected by the GC (see newFile function here: https://golang.org/src/os/file_unix.go).
What I'm looking to do, given a URL and take a screenshot of the website using Golang. I searched for results but I didn't get any. Can anyone please help me.
You can use a Go version of Selenium if you want to go that route. https://godoc.org/github.com/tebeka/selenium
There is no pure golang way to do at the moment this since it must involve a browser is some form.
The easiest path to achieve this functionality is probably:
Find a nice NodeJS library to take website screenshots
Create a NodeJS script that is suits your needs for taking screenshots (i/o and settings)
Execute this NodeJS script from Golang and handle the results in your Golang code
Not the cleanest method to get this done though - if you want it cleaner you probably have to build/find a golang package that controls a browser so you can skip the NodeJS middleman.
I solved this issue using https://github.com/mafredri/cdp and a Chrome headless docker container.
You can see my service example here: https://gist.github.com/efimovalex/9f9b815b0d5b1b7889a51d46860faf8a
A few more tools using Go and Chrome/Chromium include:
gowitness CLI app
screenshot library
web2image CLI app based on chromedp
I was writing a program for this specific task. Here is a sample code that browse google.com and takes a screenshot.
package main
import (
"time"
driver "github.com/dreygur/webdriver"
)
func main() {
url := `https://google.com`
driver.RunServer("./geckodriver")
driver.GetSession()
driver.Get(url)
time.Sleep(8 * time.Second)
driver.Screenshot("google")
time.Sleep(8 * time.Second)
defer driver.Kill()
}
To install the module, run go get github.com/dreygur/webdriver
You can use chromedp.
But you need install chrome browser!
Example :
package main
import (
"context"
"fmt"
"os"
"time"
"github.com/chromedp/chromedp"
)
func TackScreenShot(ctx context.Context, url string) ([]byte, error) {
context, cancel := chromedp.NewContext(ctx)
defer cancel()
var filebyte []byte
if err := chromedp.Run(context, chromedp.Tasks{
chromedp.Navigate(url),
chromedp.Sleep(3 * time.Second),
chromedp.CaptureScreenshot(&filebyte),
}); err != nil {
return nil, err
}
return filebyte, nil
}
func main() {
url := "https://google.com"
ctx := context.TODO()
data, err := TackScreenShot(ctx, url)
if err != nil {
panic(err)
}
defer ctx.Done()
pngFile, err := os.Create("./shot.png")
if err != nil {
panic(err)
}
defer pngFile.Close()
pngFile.Write(data)
fmt.Println("screen shot tacked!")
}
I want to write a simple webserver in go that does the following: when i go to http://example.go:8080/image, it returns a static image.
I'm following an example i found here. In this example they implement this method:
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hi there, I love %s!", r.URL.Path[1:])
}
and then refer to it here :
...
...
http.HandleFunc("/", handler)
Now, what i wanna do is serve an image instead of writing to the string.
How would i go about that?
You can serve static files using the http.FileServer function.
package main
import (
"log"
"net/http"
)
func main() {
http.Handle("/", http.StripPrefix("/", http.FileServer(http.Dir("path/to/file"))))
if err := http.ListenAndServe(":8080", nil); err != nil {
log.Fatal("ListenAndServe: ", err)
}
}
EDIT: More idiomatic code.
EDIT 2: This code above will return an image image.png when the browser requests http://example.go/image.png
The http.StripPrefix function here is strictly unnecessary in this case as the path being handled is the web root. If the images were to be served from the path http://example.go/images/image.png then the line above would need to be http.Handle("/images/", http.StripPrefix("/images/", http.FileServer(http.Dir("path/to/file")))).
Playground
I need help understanding how to demonize a process in Go.
package main
import (
"fmt"
"os"
)
func start() {
var procAttr os.ProcAttr
procAttr.Files = []*os.File{nil, nil, nil}
_, err := os.StartProcess("/Path/prog", nil, &procAttr)
if err != nil {
fmt.Printf("%v", err)
}
}
func main () {
start()
}
If you start this code on the command line the program returns control, but is still connected with cmd. Closing the cmd closes the program.
How can I decouple it from the cmd? Adding:
procAttr.Sys.HideWindow = true
Results in this error: "panic" to wrong memory pointer
I asked in 'golang-nuts', and found out that Go has a link option:
go tool 8l -o output.exe -Hwindowsgui input.8
Here is a fake daemon in go; it's simple to use: https://github.com/icattlecoder/godaemon
An example:
package main
import (
_ "github.com/icattlecoder/godaemon"
"log"
"net/http"
)
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/index", func(rw http.ResponseWriter, req *http.Request) {
rw.Write([]byte("hello, golang!\n"))
})
log.Fatalln(http.ListenAndServe(":7070", mux))
}