My 2017 in pictures.
First time in UK, so unusual to hear English everywhere after 5 years in Germany
My 2017 in pictures.
First time in UK, so unusual to hear English everywhere after 5 years in Germany
Hi guys,
this is day 18 out of 100 days of code.
To get md5 sum of a file you crypto/md5 library and io/ioutil for reading files.
package main import ( "crypto/md5" "fmt" "io/ioutil" "log" "os" ) func main() { if len(os.Args) <= 1 { log.Fatal("expected filename as parameter") } filename := os.Args[1] data, err := ioutil.ReadFile(filename) if err != nil { log.Fatal(err) } fmt.Printf("MD5 (%s) = %x\n", filename, md5.Sum(data)) }
Thanks!
Hi guys,
this is day 17 out of 100 days of code in go lang.
Today I have played with files, sorting, bytes and strings. The goal was to create a kind of indexed file where all lines are arranged alphabetically.
What I got is very slow algorithm which took 15 seconds to insert 10K strings in an empty file and 49 seconds to insert another 10K strings to the same file. So, it slowdown very quickly as size grow.
func writeLineToFileSorted(newdata string) { indexData, err := ioutil.ReadFile("db.txt") if err != nil { log.Fatal(err) } var newIndexData []string for _, line := range bytes.Split(indexData, []byte("\n")) { //fmt.Printf("%s\n", line) newIndexData = append(newIndexData, string(line)) } newIndexData = append(newIndexData, string(newdata)) sort.Strings(newIndexData) bytesData := []byte(strings.Join(newIndexData, "\n")) ioutil.WriteFile("db.txt", bytesData, 0644) }
I have to convert between strings and bytes which was kind of annoying, but maybe I am doing it wrong? Please let me know in comments.
If you want to load test it here is how:
func main() { rand.Seed(time.Now().UnixNano()) var newdata string for i := 0; i < 10000; i++ { newdata = randStringRunes(10) writeLineToFileSorted(newdata) fmt.Println(i) } } var letterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") func randStringRunes(n int) string { b := make([]rune, n) for i := range b { b[i] = letterRunes[rand.Intn(len(letterRunes))] } return string(b) }
Source code at Github
Happy coding!
Hi guys,
this is day 16 out of 100 days of code.
With help of http and ioutil packages file download and storage is quite easy task.
package main import ( "io/ioutil" "log" "net/http" ) func main() { url := "https://picsum.photos/200/300/?random" resp, err := http.Get(url) if err != nil { log.Fatal(err) } defer resp.Body.Close() image, err := ioutil.ReadAll(resp.Body) if err != nil { log.Fatal(err) } err = ioutil.WriteFile("./myimage.gif", image, 0644) if err != nil { log.Fatal(err) } }
In the example I am using Lorem Picsum service to get random image every run.
Happy coding!
Hi guys,
this is day 15 out of 100 days of go land coding.
I continue github subject and today it is github issue reader. Example demonstrate how API results which come in json format convert into struct type.
package main import ( "encoding/json" "flag" "fmt" "log" "net/http" ) func main() { repo := flag.String("repo", "", "github owner/repo e.g. golang/go") id := flag.Int("id", -1, "issue id") flag.Parse() if *id == -1 || *repo == "" { log.Fatal("--repo and --id parameters must be provided") } issue, _ := read(*repo, *id) fmt.Print(issue.Title) } // IssueData - specify data fields for new github issue submission type IssueData struct { Title string `json:"title"` Body string `json:"body"` } func read(ownerRepo string, id int) (*IssueData, error) { apiURL := fmt.Sprintf("https://api.github.com/repos/%s/issues/%d", ownerRepo, id) resp, err := http.Get(apiURL) if err != nil { log.Fatal(err) return nil, err } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { log.Fatal(err) return nil, err } var result *IssueData if err := json.NewDecoder(resp.Body).Decode(&result); err != nil { resp.Body.Close() return nil, err } return result, nil }
Happy coding!
Hi guys,
today is day 14 out of 100 days of golang coding.
This time I was playing with github issues api and made small script which create new issues in given repository. However to use the code you would need to obtain github personal token key.
The interesting part was to make http post request with custom headers.
package main import ( "bytes" "encoding/json" "flag" "fmt" "io/ioutil" "log" "net/http" ) func main() { token := flag.String("token", "", "github auth token") repo := flag.String("repo", "", "github owner/repo e.g. golang/go") title := flag.String("title", "", "title for new issue") body := flag.String("body", "", "body for new issue") flag.Parse() if *token == "" || *title == "" || *repo == "" { log.Fatal("--token, --repo and --title parameters must be provided") } create(*repo, *title, *body, *token) } // NewIssue - specify data fields for new github issue submission type NewIssue struct { Title string `json:"title"` Body string `json:"body"` } func create(ownerRepo, title, body, token string) { apiURL := "https://api.github.com/repos/" + ownerRepo + "/issues" //title is the only required field issueData := NewIssue{Title: title, Body: body} //make it json jsonData, _ := json.Marshal(issueData) //creating client to set custom headers for Authorization client := &http.Client{} req, _ := http.NewRequest("POST", apiURL, bytes.NewReader(jsonData)) req.Header.Set("Authorization", "token "+token) resp, err := client.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close() if resp.StatusCode != http.StatusCreated { fmt.Printf("Response code is is %d\n", resp.StatusCode) body, _ := ioutil.ReadAll(resp.Body) //print body as it may contain hints in case of errors fmt.Println(string(body)) log.Fatal(err) } }
Example usage is as follow:
go build github_issue.go ./github_issue --token="5daf49b235c41d53ba6fsfasdfasdfasfsad" --repo="vorozhko/go-tutor" --title="my new issue 3" --body="test"
Hi guys,
today is day 13 out of 100 days of code in go!
This time it is example of fetching issues from github and categorizing by created date.
To run example you need to install github issue searcher package from The Go Progamming Language book
go get gopl.io/ch4/github
Full code
package main import ( "fmt" "log" "os" "time" "gopl.io/ch4/github" ) func main() { result, err := github.SearchIssues(os.Args[1:]) if err != nil { log.Fatal(err) } fmt.Printf("%d issues:\n", result.TotalCount) var dateformat string for _, item := range result.Items { days := int(time.Since(item.CreatedAt).Hours()) / 24 if days < 30 { dateformat = "less than a month old" } else if days < 365 { dateformat = "less than a year old" } else { dateformat = "more than a year old" } fmt.Printf("%s, #%-5d %9.9s %.55s\n", dateformat, item.Number, item.User.Login, item.Title) } }
Happy coding!
Hi guys,
this is day 12 out of 100 days of code. I didn’t post for a while, because I did a small break for hackaton, but now I am back on track.
When you print a map using range function it will access elements in randomized order. So, if you want to print map in sorted order you have to sort keys first. See how:
package main import ( "fmt" "sort" ) func main() { m := map[string]int{"A": 1, "B": 2, "AA": 1, "C": 3, "BBB": 2} //reverse keys and values of m map var mapKeys []string fmt.Print("Unsorted:\n") for k, v := range m { fmt.Printf("%s -> %d\n", k, v) mapKeys = append(mapKeys, k) } sort.Strings(mapKeys) fmt.Print("Sorted:\n") for _, v := range mapKeys { fmt.Printf("%s -> %d\n", v, m[v]) } }
Solution is to use additional array for keys and sort it in wished order.
Happy coding!
Hi guys,
this is day 11 out of 100 days of go coding.
This time it is very short demo of go maps and simple sort by map values. Note that the example below will not work correctly if values has duplicates.
package main import ( "fmt" "sort" ) func main() { //init a map with strings keys and int values var m = make(map[string]int) m["Sun"] = 7 m["Sat"] = 6 m["Fri"] = 5 m["Thu"] = 4 m["Mon"] = 1 m["Tue"] = 2 m["Wed"] = 3 //reverse keys and values of m map var days = make(map[int]string) //array of indexes for sorting var daykeys = make([]int, len(m)) fmt.Print("Unsorted days of week\n") counter := 0 for k, v := range m { fmt.Printf("%s -> %d\n", k, v) days[v] = k daykeys[counter] = v counter++ } //sort indexes array here sort.Ints(daykeys) fmt.Print("Sorted days of week\n") for _, v := range daykeys { fmt.Printf("%s\n", days[v]) } }
I believe this code has a lot of room for optimization, so if you know how please write me in comments or ping me in twitter with your version.
Happy coding everyone!
Hi, this is day 9 out of 100 days of code in go.
Today I am playing with struct type. Struct is a go way to define custom types. Use it when standard types doesn’t suite you. Enough words, lets see code examples.
Classic example Employee type
// Employee - new type type Employee struct { ID int Name string Manager *Employee //reference to itself }
ID and Name fields is quite obvious. Manager field is the same type as struct itself, so it must be a reference type and in our business logic will point to Manager data.
Lets create first employee
func main() { // Example of initializing new Employee var worker Employee worker.ID = 1 worker.Name = "Petia Pyatochkin" PrintEmployee(worker) } // PrintEmployee - print data in nice format func PrintEmployee(e Employee) { fmt.Printf("ID = %d\nName = %s\n", e.ID, e.Name) }
Struct fields are accessible using dot notation.
Lets define a manager now and improve print function, so it will print Manger if such exist
func main() { // Example of initializing new struct data var worker Employee worker.ID = 1 worker.Name = "Petia Pyatochkin" PrintEmployee(worker) // Struct can reference on it's own type //Lets define manager for an employee var manager Employee manager.ID = 2 manager.Name = "Middle Level" //using pointer we create a reference to manager struct and keep hierachy of oranization worker.Manager = &manager PrintEmployee(worker) } // PrintEmployee - print data in nice format func PrintEmployee(e Employee) { fmt.Printf("ID = %d\nName = %s\n", e.ID, e.Name) //if e.Manager is defined print manager data if e.Manager != nil { fmt.Printf("Manager of %s:\n", e.Name) //recursively go through managers tree PrintEmployee(*e.Manager) return } fmt.Print("----------\n\n") }
New employee manager is created the same way as first worker variable. When using a reference to new manager variable we assign a manager to worker.
PrintEmployee function has some changes too. First it has new check if Manager reference is not nil and if so using recursion it prints Manager data.
Lets add another Employee, so we will have 3 level management organization
unc main() { // Example of initializing new struct data var worker Employee worker.ID = 1 worker.Name = "Petia Pyatochkin" PrintEmployee(worker) // Struct can reference on it's own type //Lets define manager for an employee var manager Employee manager.ID = 2 manager.Name = "Middle Level" //using pointer we create a reference to manager struct and keep hierachy of oranization worker.Manager = &manager PrintEmployee(worker) //define fields ID and Name using struct literals var cto = Employee{ID: 3, Name: "cto"} manager.Manager = &cto //should print 3 level org structure PrintEmployee(worker) }
Note that new cto variable is using struct literals to define fields values in variable initialization step.
Output of above will be 3 level organization structure:
$ go run struct.go ID = 1 Name = Petia Pyatochkin ---------- ID = 1 Name = Petia Pyatochkin Manager of Petia Pyatochkin: ID = 2 Name = Middle Level ---------- ID = 1 Name = Petia Pyatochkin Manager of Petia Pyatochkin: ID = 2 Name = Middle Level Manager of Middle Level: ID = 3 Name = cto ----------
That’s what you need to know about struct type to use it efficiently in you go programs.
Happy coding!
Source code at Github.