Learning Go Episode 2 – Further into packages, dependencies, application creation, and IDE’s

Episode Post & Video Links:  1, 2 (this post), 3, 4, 5, 6, 7, and 8. Non-linked are in the works! Videos available now on Youtube however, so check em’ out!

In episode two I went over a lot of the material that I covered in the first episode, but added more context, historical reasons certain things are the way they are in Go and the stack, and went over a number of new elements of information too. One thing I got further into this episode is the package and dependency management with Go Dep and also how to create a package, or dependency library for use in other Go libraries or applications. It’s just a small introduction in this episode, but pivotal to future episodes, as I’ll be jumping further into library creation and related details.

In this post I’ve got the time point breakdown like usual,  but also a few additional bits of information and code examples, plus links to the repository I’ve setup for this particular episode. The quick links to those references are below, and also I’ll link at particular call out points within the time points.

Quick Links:

Key Topics Covered

Data Types, Packages, and Dependency Management

2:52 – Fumbling through getting started. It is after all Saturday morning!
3:00 – Recap of what we covered in the first session. Includes a quick review of the previous session code too, such as the random data generation library we setup and used.
6:40 – Covering some specifics of the IDE’s, the stories of the benefits of Go having a specific and somewhat detailed convention to the way syntax, variables, and related features are used.
7:40 – Covering gofmt and what it gives us.
9:45 – Looking at the gofmt plugins and IDE features around the conventions.
14:06 – New example time! In this one, I work through an example showing how to find duplicate lines in passed in text.

Duplicate Line Finder

I went through the various steps of creating the code, but then took a little bit of a detour from the example in the book. Instead of lines by the CLI it takes in content from a text file. The code in main.go ended up like this.


package main
import (
"bufio"
"fmt"
"os"
)
func main() {
counts := make(map[string]int)
files := os.Args[1:]
if len(files) == 0 {
countLines(os.Stdin, counts)
} else {
for _, arg := range files {
f, err := os.Open(arg)
if err != nil {
fmt.Printf("The Error Happened! %s", os.Stderr)
continue
}
countLines(f, counts)
errFile := f.Close()
if errFile != nil {
fmt.Println("Holy moley the file didn't close correctly!")
}
}
}
for line, n := range counts {
if n > 1 {
fmt.Printf("%d\t%s\n", n, line)
}
}
}
func countLines(f *os.File, counts map[string]int) {
input := bufio.NewScanner(f)
for input.Scan() {
counts[input.Text()]++
}
}

view raw

main.go

hosted with ❤ by GitHub

Then if you’d like to check out the text file and remaining content in that project, check out the master branch of the episode 2 repo.

36:34 – Here I take a thorough step through committing this project to github, which is the included repo in this post. However I step through the interface of using Jetbrains Goland to do the commit, how it enables gofmt and other features to improve the condition of code and ensure it meets linter demands and related crtieria. I also cover the .gitignore file and other elements to create a usable repository.
44:30 – Setting up the repository for today’s code at https://github.com/Adron/learning-go-…
50:00 – Setup of the key again for using Github. How to setup your ssh keys using ssh-keygen.
56:00 – Going beyond just the language, and building out a Go build on Travis CI.
1:10:16 – Creating a new branch for the next code examples and topics. At this point I shift into type declarations. Working through some constants, very basic function declarations, and related capabilities to calculate temperatures between Fahrenheit and Celsius.

The tempApp Branch is available in the repository here.

At this point I shift into type declarations. Working through some constants, very basic function declarations, and related capabilities to calculate temperatures between Fahrenheit and Celsius.

During this point, we take a look at our first package. This package ended up looking like this.


package tempconv
type Celsius float64
type Fahrenheit float64
const (
AbsoluteZeroC Celsius = -273.15
FreezingC Celsius = 0
BoilingC Celsius = 100
)
func CelsiusToFahrenheit(c Celsius) Fahrenheit {
return Fahrenheit(c*9/5 + 32)
}
func FahrenheitToCelsius(f Fahrenheit) Celsius {
return Celsius((f – 32) * 5 / 9)
}

In the main.go file, I showed how you can use this package by adding a respective import shown in this code.


package main
import (
"fmt"
tempconv "github.com/Adron/awesomeProject/tempconv"
)
func main() {
fmt.Println("Temperatures are hard to figure off the top of one's mind!")
boilingF := tempconv.CelsiusToFahrenheit(BoilingC)
fmt.Printf("%v\n", boilingF)
fmt.Printf("%s\n", boilingF)
fmt.Println(boilingF)
fmt.Printf("%g\n", boilingF)
}

view raw

main.go

hosted with ❤ by GitHub

1:17:54 – At this point, to increase readability of font sizes I get into the various Goland IDE options.
1:38:12 – Creating the final branch for this session to pull in a public package and use it in project. For this, I pull in a random data generation package to use in some application code.


package main
import (
"fmt"
randomdata "github.com/Pallinder/go-randomdata"
)
func main() {
// Print a random silly name
fmt.Println(randomdata.SillyName())
// Print a male title
fmt.Println(randomdata.Title(randomdata.Male))
// Print a female title
fmt.Println(randomdata.Title(randomdata.Female))
// Print a title with random gender
fmt.Println(randomdata.Title(randomdata.RandomGender))
// Print a male first name
fmt.Println(randomdata.FirstName(randomdata.Male))
// Print a female first name
fmt.Println(randomdata.FirstName(randomdata.Female))
// Print a last name
fmt.Println(randomdata.LastName())
// Print a male name
fmt.Println(randomdata.FullName(randomdata.Male))
// Print a female name
fmt.Println(randomdata.FullName(randomdata.Female))
// Print a name with random gender
fmt.Println(randomdata.FullName(randomdata.RandomGender))
// Print an email
fmt.Println(randomdata.Email())
// Print a country with full text representation
fmt.Println(randomdata.Country(randomdata.FullCountry))
// Print a country using ISO 3166-1 alpha-2
fmt.Println(randomdata.Country(randomdata.TwoCharCountry))
// Print a country using ISO 3166-1 alpha-3
fmt.Println(randomdata.Country(randomdata.ThreeCharCountry))
// Print BCP 47 language tag
fmt.Println(randomdata.Locale())
// Print a currency using ISO 4217
fmt.Println(randomdata.Currency())
// Print the name of a random city
fmt.Println(randomdata.City())
// Print the name of a random american state
fmt.Println(randomdata.State(randomdata.Large))
// Print the name of a random american state using two chars
fmt.Println(randomdata.State(randomdata.Small))
// Print an american sounding street name
fmt.Println(randomdata.Street())
// Print an american sounding address
fmt.Println(randomdata.Address())
// Print a random number >= 10 and < 20
fmt.Println(randomdata.Number(10, 20))
// Print a number >= 0 and < 20
fmt.Println(randomdata.Number(20))
// Print a random float >= 0 and < 20 with decimal point 3
fmt.Println(randomdata.Decimal(0, 20, 3))
// Print a random float >= 10 and < 20
fmt.Println(randomdata.Decimal(10, 20))
// Print a random float >= 0 and < 20
fmt.Println(randomdata.Decimal(20))
// Print a bool
fmt.Println(randomdata.Boolean())
// Print a paragraph
fmt.Println(randomdata.Paragraph())
// Print a postal code
fmt.Println(randomdata.PostalCode("SE"))
// Print a set of 2 random numbers as a string
fmt.Println(randomdata.StringNumber(2, "-"))
// Print a set of 2 random 3-Digits numbers as a string
fmt.Println(randomdata.StringNumberExt(2, "-", 3))
// Print a random string sampled from a list of strings
fmt.Println(randomdata.StringSample("my string 1", "my string 2", "my string 3"))
// Print a valid random IPv4 address
fmt.Println(randomdata.IpV4Address())
// Print a valid random IPv6 address
fmt.Println(randomdata.IpV6Address())
// Print a browser's user agent string
fmt.Println(randomdata.UserAgentString())
// Print a day
fmt.Println(randomdata.Day())
// Print a month
fmt.Println(randomdata.Month())
// Print full date like Monday 22 Aug 2016
fmt.Println(randomdata.FullDate())
// Print full date <= Monday 22 Aug 2016
fmt.Println(randomdata.FullDateInRange("2016-08-22"))
// Print full date >= Monday 01 Aug 2016 and <= Monday 22 Aug 2016
fmt.Println(randomdata.FullDateInRange("2016-08-01", "2016-08-22"))
// Print phone number according to e.164
fmt.Println(randomdata.PhoneNumber())
// Get a complete and randomised profile of data generally used for users
// There are many fields in the profile to use check the Profile struct definition in fullprofile.go
profile := randomdata.GenerateProfile(randomdata.Male | randomdata.Female | randomdata.RandomGender)
fmt.Printf("The new profile's username is: %s and password (md5): %s\n", profile.Login.Username, profile.Login.Md5)
// Get a random country-localised street name for Great Britain
fmt.Println(randomdata.StreetForCountry("GB"))
// Get a random country-localised street name for USA
fmt.Println(randomdata.StreetForCountry("US"))
// Get a random country-localised province for Great Britain
fmt.Println(randomdata.ProvinceForCountry("GB"))
// Get a random country-localised province for USA
fmt.Println(randomdata.ProvinceForCountry("US"))
}

view raw

main.go

hosted with ❤ by GitHub

1:44:50 – Further discussion and explanation of what to include in .gitignore files to manage projects, but also what is and isn’t included for dependencies and other details around all of this.
2:13:22 – The wicked awesome hacker outtro.