How to fork a process - fork

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))
}

Related

How to use Gorilla Sessions in Golang in different packages

I have main package (main.go):
package main
import (
"github.com/gorilla/sessions"
...
)
func main() {
var store = sessions.NewCookieStore([]byte("secret"))
http.HandleFunc("/", routes.Index)
http.ListenAndServe(":8080", nil)
...
And I have another package (index.go):
package routes
import (
"github.com/gorilla/sessions"
..
)
func Index(res http.ResponseWriter, req *http.Request) {
session, _ := store.Get(req, "session-name")
...
How can I get session value from another package? Or should I pass it to my Handler (if yes how to do it?).
I am new in Golang. Please, help.
I generally wrap my dependencies in their own package, which let's me abstract away some of the common things I do. For sessions, I usually use the same session name most of the time, so I would usually have something like this:
package sessions
import (
"os"
gsessions "github.com/gorilla/sessions"
)
var store = gsessions.NewCookieStore([]byte(os.Getenv("SESSION_KEY")))
func Get(req *http.Request) (*gsessions.Session, error) {
return store.Get(req, "default-session-name")
}
func GetNamed(req *http.Request, name string) (*gsessions.Session, error) {
return store.Get(req, name)
}
And then anywhere else you can just import your own sessions package:
import (
"net/http"
"github.com/yourpackage/sessions"
)
func Index(rw http.ResponseWriter, r *http.Request) {
session, err := sessions.Get(r)
if err != nil {
panic(err)
}
session.Values["test"] = "test"
session.Save(r, rw)
}
Even better would be to only return an interface of some sort from sessions, and completely wrap the gorilla/sessions so that aren't dependent on it anywhere except for your own sessions package.

Can Anyone help me with this GoLand terminal Error

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....

Some confusion of Go `net/http` under high concurrency

Some confusion under high concurrency.
I use wrk to test Gin, there's someting uncertainty. Gin seems doesn't concurrency safe.
package main
import (
"fmt"
"sync/atomic"
"github.com/gin-gonic/gin"
)
var count int64 = 0
func Test(c *gin.Context) {
atomic.AddInt64(&count, 1)
fmt.Println(count)
c.String(200, "success")
}
func main() {
gin.SetMode(gin.DebugMode)
router := gin.New()
router.GET("test", Test)
router.Run(":8080")
}
Test shell code
wrk -t50 -c50 -d 1s http://localhost:8080/test
Gin output duplicate data
========update========
even if the print code like this.
countCopy := count
go func() {
fmt.Println(countCopy)
}()
I also use ab test it, the same problem.
========update========
The same with net/http, still has duplicate data.
package main
import (
"fmt"
"net/http"
"sync/atomic"
)
var count int64 = 0
func Test(w http.ResponseWriter, req *http.Request) {
atomic.AddInt64(&count, 1)
fmt.Println(count)
w.Write([]byte("success"))
}
func main() {
http.HandleFunc("/test", Test)
http.ListenAndServe(":8080", nil)
}
I try to use log package, which is safe from concurrent goroutines . The same.
log.Println(countCopy)
You have to use the returned value from atomic.AddInt64(&count, 1), as count can change before you have a chance to print it:
func Test(c *gin.Context) {
current := atomic.AddInt64(&count, 1)
fmt.Println(current)
c.String(200, "success")
}

Telnet client in go

I am trying to send 'hello world' to the telnet server from go client. In the documentation I have found example:
var caller telnet.Caller = telnet.StandardCaller
telnet.DialToAndCall("localhost:5555", caller)
What is the next step to send 'helloworld' now?
Example of programmatic connection using go-telnet
func SetTest() {
conn, _ := telnet.DialTo("localhost:5555")
conn.Write([]byte("hello world"))
conn.Write([]byte("\n"))
}
In the example below you can see that the CallTELNET uses stdin and stdout to allow the user of the program to communicate through telnet. You can send "hello world" by running the program and typing the desired text you wish to send followed by the enter key.
package main
import (
"bufio"
"fmt"
"log"
"os"
"github.com/reiver/go-oi"
"github.com/reiver/go-telnet"
)
type caller struct{}
func (c caller) CallTELNET(ctx telnet.Context, w telnet.Writer, r telnet.Reader) {
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
oi.LongWrite(w, scanner.Bytes())
oi.LongWrite(w, []byte("\n"))
}
}
func main() {
fmt.Printf("Dial to %s:%d\n", "localhost", 8080)
err := telnet.DialToAndCall(fmt.Sprintf("%s:%d", "localhost", 8080), caller{})
if err != nil {
log.Fatal(err)
}
}
Examples found here and here
The telnet library implements the 'Writer' type. The Writer Type has a Write method.

How to run Binary Files inside GoLang Program?

I want to execute Binary Files inside GoLang Program.
Here is my code:
package main
import (
"fmt"
"os/exec"
)
func main() {
output, _ := exec.Command("/home/user/Golang/bin/hello").Output()
fmt.Println(output)
}
But I get the output as: []
Thanks in advance.
I can get the output.
package main
import (
"fmt"
"os/exec"
)
func main() {
output, err := exec.Command("/Users/duguying/gopath/bin/test").Output()
if err!=nil {
fmt.Println(err.Error())
}
fmt.Println(string(output))
}
check you binary file first or binary filepath is correcting. try to print out your error message.
When I'm looking at the source of the exec.Command() it doesnt return an error but only returns Cmd which is struct in the package exe :
source
....
func Command(name string, arg ...string) *Cmd {
cmd := &Cmd{
Path: name,
Args: append([]string{name}, arg...),
}
if filepath.Base(name) == name {
if lp, err := LookPath(name); err != nil {
cmd.lookPathErr = err
} else {
cmd.Path = lp
}
}
return cmd
}
....
I have succesfully got the binary file running using this code :
package main
import (
"fmt"
"os/exec"
)
func main() {
command:= exec.Command("Your binary file path")
// set var to get the output
var out bytes.Buffer
// set the output to our variable
command.Stdout = &out
err = command.Run()
if err != nil {
log.Println(err)
}
fmt.Println(out.String())
}
This one works for me for running a binary file that will print some random string.

Resources