multi worker Go program - multithreading

I have a simple program that will generate random string and numbers and put it in specific format:
output:
A=SKEK673KJK B=67235 C=PDCNE39JSWL
I have 4 func including main:
func genRandInt() string {
//return string(randInt)
}
func genRandStr() string {
//return (randStr)
}
func genFakeData() string {
fmt.Println("A=" + genRanStr() + genRandInt().....etc)
}
func main() {
genFackeData()
}
so far the program working fine, and I am executing it via bash loop in order to run it many time in order to generate huge traffic on the server, but I couldn't reach the generated data as I was expected, what I need to run genFackeData() in many worker (e.g 50 worker) how I can achieve that in GO ?
(by the way this is very simple version of my program, to not make
complicated I have written the simple sample of what I need)

If i am understood your wish right then try to play here https://play.golang.org/p/q_r8PATh6_U
package main
import (
"fmt"
"sync"
)
func genFakeData(wg *sync.WaitGroup, i int) {
fmt.Println("A =",i + 1)
wg.Done()
}
func main() {
var wg sync.WaitGroup
for i:=0 ; i<50 ; i++ {
wg.Add(1)
go genFakeData(&wg, i)
}
wg.Wait()
}

Related

String splitting before character

I'm new to go and have been using split to my advantage. Recently I came across a problem I wanted to split something, and keep the splitting char in my second slice rather than removing it, or leaving it in the first slice as with SplitAfter.
For example the following code:
strings.Split("email#email.com", "#")
returned: ["email", "email.com"]
strings.SplitAfter("email#email.com", "#")
returned: ["email#", "email.com"]
What's the best way to get ["email", "#email.com"]?
Use strings.Index to find the # and slice to get the two parts:
var part1, part2 string
if i := strings.Index(s, "#"); i >= 0 {
part1, part2 = s[:i], s[i:]
} else {
// handle case with no #
}
Run it on the playground.
Could this work for you?
s := strings.Split("email#email.com", "#")
address, domain := s[0], "#"+s[1]
fmt.Println(address, domain)
// email #email.com
Then combing and creating a string
var buffer bytes.Buffer
buffer.WriteString(address)
buffer.WriteString(domain)
result := buffer.String()
fmt.Println(result)
// email#email.com
You can use bufio.Scanner:
package main
import (
"bufio"
"strings"
)
func email(data []byte, eof bool) (int, []byte, error) {
for i, b := range data {
if b == '#' {
if i > 0 {
return i, data[:i], nil
}
return len(data), data, nil
}
}
return 0, nil, nil
}
func main() {
s := bufio.NewScanner(strings.NewReader("email#email.com"))
s.Split(email)
for s.Scan() {
println(s.Text())
}
}
https://golang.org/pkg/bufio#Scanner.Split

Thesaurus of strings: because so many different start characters, need to use Split with not equal to logic

I have a .dat file that is a dictionary/thesaurus containing about 300k lines
For each word, the following lines below it that have a word in brackets at the start of the string are the thesaurus' alternatives with the word in the brackets being the type. So a noun or adjective. For example:
acceptant|1
(adj)|acceptive|receptive
acceptation|3
(noun)|acceptance
(noun)|word meaning|word sense|sense|signified
(noun)|adoption|acceptance|espousal|blessing|approval|approving
accepted|6
(adj)|recognized|recognised|acknowledged
(adj)|undisputed|uncontroversial |noncontroversial
(adj)|standard
(adj)|acceptable|standard |received
(adj)|established |constituted
(adj)|received|conventional
accepting|1
(adj)|acceptive
So in the above there are 4 words from the dictionary, but each word has multiple different entries for the thesaurus
I want to split the strings using:
strings.Split(dictionary, !"(")
Meaning anything that isn't the "(" character. This is because it's an extensive dictionary with slang and abbreviations and whatnot. But I can't work out how to use the not equal to operator
Does anyone know how to use split with not equal to logic? Or can anyone suggest some clever alternative ideas?
#MostafaSolati's solution could be improved by being written more efficiently.
package main
import (
"bufio"
"bytes"
"fmt"
"os"
)
func main() {
file, _ := os.Open("dic.dat")
scanner := bufio.NewScanner(file)
for scanner.Scan() {
data := scanner.Bytes()
if bytes.HasPrefix(data, []byte("(")) {
continue
}
line := scanner.Text()
fmt.Println(line)
}
}
Output:
acceptant|1
acceptation|3
accepted|6
accepting|1
By design, Go code is expected to be efficient. The Go standard library testing package includes a benchmark feature.
It's important to avoid unnecessary conversions and allocations. For example, converting byte slices read from a file to a strings, an allocation and a copy.
In this case, we only need to convert accepted data to a string. For example, prefer Bytes to Text.
$ go test dict_test.go -bench=.
BenchmarkText-4 500 2486306 ns/op 898528 B/op 14170 allocs/op
BenchmarkBytes-4 1000 1489828 ns/op 34080 B/op 609 allocs/op
$
Sample benchmark data:
KEY: Aback.
SYN: Backwards, rearwards, aft, abaft, astern, behind, back.
ANT: Onwards, forwards, ahead, before, afront, beyond, afore.
=
KEY: Abandon.
SYN: Leave, forsake, desert, renounce, cease, relinquish,
discontinue, castoff, resign, retire, quit, forego, forswear,
depart from, vacate, surrender, abjure, repudiate.
ANT: Pursue, prosecute, undertake, seek, court, cherish, favor,
protect, claim, maintain, defend, advocate, retain, support, uphold,
occupy, haunt, hold, assert, vindicate, keep.
=
dict_test.go:
package main
import (
"bufio"
"bytes"
"fmt"
"io/ioutil"
"os"
"strings"
"testing"
)
func BenchmarkText(b *testing.B) {
b.ReportAllocs()
for N := 0; N < b.N; N++ {
file := bytes.NewReader(benchData)
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := scanner.Text()
if !strings.HasPrefix(line, "KEY") {
continue
}
_ = line // process line
}
if err := scanner.Err(); err != nil {
b.Fatal(err)
}
}
}
func BenchmarkBytes(b *testing.B) {
b.ReportAllocs()
for N := 0; N < b.N; N++ {
file := bytes.NewReader(benchData)
scanner := bufio.NewScanner(file)
for scanner.Scan() {
data := scanner.Bytes()
if !bytes.HasPrefix(data, []byte("KEY")) {
continue
}
line := scanner.Text()
_ = line // process line
}
if err := scanner.Err(); err != nil {
b.Fatal(err)
}
}
}
var benchData = func() []byte {
// A Complete Dictionary of Synonyms and Antonyms by Samuel Fallows
// http://www.gutenberg.org/files/51155/51155-0.txt
data, err := ioutil.ReadFile(`/home/peter/dictionary.51155-0.txt`)
if err != nil {
panic(err)
}
return data
}()
package main
import (
"bufio"
"fmt"
"os"
"strings"
)
func main() {
file, _ := os.Open("dic.dat")
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := scanner.Text()
if strings.HasPrefix(line, "(") {
continue
}
fmt.Println(line)
}
}

Call functions with special prefix/suffix

I have a package named "seeder":
package seeder
import "fmt"
func MyFunc1() {
fmt.Println("I am Masood")
}
func MyFunc2() {
fmt.Println("I am a programmer")
}
func MyFunc3() {
fmt.Println("I want to buy a car")
}
Now I want to call all functions with MyFunc prefix
package main
import "./seeder"
func main() {
for k := 1; k <= 3; k++ {
seeder.MyFunc1() // This calls MyFunc1 three times
}
}
I want something like this:
for k := 1; k <= 3; k++ {
seeder.MyFunc + k ()
}
and this output:
I am Masood
I am a programmer
I want to buy a car
EDIT1:
In this example, parentKey is a string variable which changed in a loop
for parentKey, _ := range uRLSjson{
pppp := seeder + "." + strings.ToUpper(parentKey)
gorilla.HandleFunc("/", pppp).Name(parentKey)
}
But GC said:
use of package seeder without selector
You can't get a function by its name, and that is what you're trying to do. The reason is that if the Go tool can detect that a function is not referred to explicitly (and thus unreachable), it may not even get compiled into the executable binary. For details see Splitting client/server code.
With a function registry
One way to do what you want is to build a "function registry" prior to calling them:
registry := map[string]func(){
"MyFunc1": MyFunc1,
"MyFunc2": MyFunc2,
"MyFunc3": MyFunc3,
}
for k := 1; k <= 3; k++ {
registry[fmt.Sprintf("MyFunc%d", k)]()
}
Output (try it on the Go Playground):
Hello MyFunc1
Hello MyFunc2
Hello MyFunc3
Manual "routing"
Similar to the registry is inspecting the name and manually routing to the function, for example:
func callByName(name string) {
switch name {
case "MyFunc1":
MyFunc1()
case "MyFunc2":
MyFunc2()
case "MyFunc3":
MyFunc3()
default:
panic("Unknown function name")
}
}
Using it:
for k := 1; k <= 3; k++ {
callByName(fmt.Sprintf("MyFunc%d", k))
}
Try this on the Go Playground.
Note: It's up to you if you want to call the function identified by its name in the callByName() helper function, or you may choose to return a function value (of type func()) and have it called in the caller's place.
Transforming functions to methods
Also note that if your functions would actually be methods of some type, you could do it without a registry. Using reflection, you can get a method by name: Value.MethodByName(). You can also get / enumerate all methods without knowing their names using Value.NumMethod() and Value.Method() (also see Type.NumMethod() and Type.Method() if you need the name of the method or its parameter types).
This is how it could be done:
type MyType int
func (m MyType) MyFunc1() {
fmt.Println("Hello MyFunc1")
}
func (m MyType) MyFunc2() {
fmt.Println("Hello MyFunc2")
}
func (m MyType) MyFunc3() {
fmt.Println("Hello MyFunc3")
}
func main() {
v := reflect.ValueOf(MyType(0))
for k := 1; k <= 3; k++ {
v.MethodByName(fmt.Sprintf("MyFunc%d", k)).Call(nil)
}
}
Output is the same. Try it on the Go Playground.
Another alternative would be to range over an array of your functions
package main
import (
"fmt"
)
func MyFunc1() {
fmt.Println("I am Masood")
}
func MyFunc2() {
fmt.Println("I am a programmer")
}
func MyFunc3() {
fmt.Println("I want to buy a car")
}
func main() {
for _, fn := range []func(){MyFunc1, MyFunc2, MyFunc3} {
fn()
}
}

Can you pass a struct fieldname in to a function in golang?

Say for example you have something like this, trying to make the example as simple as possible.
type Home struct {
Bedroom string
Bathroom string
}
How do you pass the field name, or can you, to a function?
func (this *Home) AddRoomName(fieldname, value string) {
this.fieldname = value
}
Obviously that does not work... The only way I can see to do this is to use two functions which adds a lot of extra code when the struct gets really big and has a lot of similar code.
func (this *Home) AddBedroomName(value string) {
this.Bedroom = value
}
func (this *Home) AddBathroomName(value string) {
this.Bathroom = value
}
The only way that I am aware of is to use reflection:
func (this *Home) AddRoomName(fieldname, value string) {
h := reflect.ValueOf(this).Elem()
h.FieldByName(fieldname).Set(reflect.ValueOf(value))
return
}
http://play.golang.org/p/ZvtF_05CE_
One more idea that comes to my mind is like this, not sure if it makes sense in your case though:
func Set(field *string, value string) {
*field = value
}
home := &Home{"asd", "zxc"}
fmt.Println(home)
Set(&home.Bedroom, "bedroom")
Set(&home.Bathroom, "bathroom")
fmt.Println(home)
http://play.golang.org/p/VGb69OLX-X
Use type assertions on an interface value:
package main
import "fmt"
type Test struct {
S string
I int
}
func (t *Test) setField(name string, value interface{}) {
switch name {
case "S":
t.S = value.(string)
case "I":
t.I = value.(int)
}
}
func main() {
t := &Test{"Hello", 0}
fmt.Println(t.S, t.I)
t.setField("S", "Goodbye")
t.setField("I", 1)
fmt.Println(t.S, t.I)
}

How can I read a whole file into a string variable

I have lots of small files, I don't want to read them line by line.
Is there a function in Go that will read a whole file into a string variable?
Use ioutil.ReadFile:
func ReadFile(filename string) ([]byte, error)
ReadFile reads the file named by filename and returns the contents. A successful call
returns err == nil, not err == EOF. Because ReadFile reads the whole file, it does not treat
an EOF from Read as an error to be reported.
You will get a []byte instead of a string. It can be converted if really necessary:
s := string(buf)
Edit: the ioutil package is now deprecated: "Deprecated: As of Go 1.16, the same functionality is now provided by package io or package os, and those implementations should be preferred in new code. See the specific function documentation for details." Because of Go's compatibility promise, ioutil.ReadMe is safe, but #openwonk's updated answer is better for new code.
If you just want the content as string, then the simple solution is to use the ReadFile function from the io/ioutil package. This function returns a slice of bytes which you can easily convert to a string.
Go 1.16 or later
Replace ioutil with os for this example.
package main
import (
"fmt"
"os"
)
func main() {
b, err := os.ReadFile("file.txt") // just pass the file name
if err != nil {
fmt.Print(err)
}
fmt.Println(b) // print the content as 'bytes'
str := string(b) // convert content to a 'string'
fmt.Println(str) // print the content as a 'string'
}
Go 1.15 or earlier
package main
import (
"fmt"
"io/ioutil"
)
func main() {
b, err := ioutil.ReadFile("file.txt") // just pass the file name
if err != nil {
fmt.Print(err)
}
fmt.Println(b) // print the content as 'bytes'
str := string(b) // convert content to a 'string'
fmt.Println(str) // print the content as a 'string'
}
I think the best thing to do, if you're really concerned about the efficiency of concatenating all of these files, is to copy them all into the same bytes buffer.
buf := bytes.NewBuffer(nil)
for _, filename := range filenames {
f, _ := os.Open(filename) // Error handling elided for brevity.
io.Copy(buf, f) // Error handling elided for brevity.
f.Close()
}
s := string(buf.Bytes())
This opens each file, copies its contents into buf, then closes the file. Depending on your situation you may not actually need to convert it, the last line is just to show that buf.Bytes() has the data you're looking for.
This is how I did it:
package main
import (
"fmt"
"os"
"bytes"
"log"
)
func main() {
filerc, err := os.Open("filename")
if err != nil{
log.Fatal(err)
}
defer filerc.Close()
buf := new(bytes.Buffer)
buf.ReadFrom(filerc)
contents := buf.String()
fmt.Print(contents)
}
You can use strings.Builder:
package main
import (
"io"
"os"
"strings"
)
func main() {
f, err := os.Open("file.txt")
if err != nil {
panic(err)
}
defer f.Close()
b := new(strings.Builder)
io.Copy(b, f)
print(b.String())
}
Or if you don't mind []byte, you can use
os.ReadFile:
package main
import "os"
func main() {
b, err := os.ReadFile("file.txt")
if err != nil {
panic(err)
}
os.Stdout.Write(b)
}
For Go 1.16 or later you can read file at compilation time.
Use the //go:embed directive and the embed package in Go 1.16
For example:
package main
import (
"fmt"
_ "embed"
)
//go:embed file.txt
var s string
func main() {
fmt.Println(s) // print the content as a 'string'
}
I'm not with computer,so I write a draft. You might be clear of what I say.
func main(){
const dir = "/etc/"
filesInfo, e := ioutil.ReadDir(dir)
var fileNames = make([]string, 0, 10)
for i,v:=range filesInfo{
if !v.IsDir() {
fileNames = append(fileNames, v.Name())
}
}
var fileNumber = len(fileNames)
var contents = make([]string, fileNumber, 10)
wg := sync.WaitGroup{}
wg.Add(fileNumber)
for i,_:=range content {
go func(i int){
defer wg.Done()
buf,e := ioutil.Readfile(fmt.Printf("%s/%s", dir, fileName[i]))
defer file.Close()
content[i] = string(buf)
}(i)
}
wg.Wait()
}

Resources