Wednesday, 12 June 2019

Introduction to Go language

Here are some notes on Go language features, packages and tools.

---

For the build tools to produce an executable, the function main must be declared, and it
becomes the entry point for the program.

Function main is located in a package called main.
If your main function doesn’t exist in package main, the build tools won’t produce an executable.

Every code file in Go belongs to a package, and main.go is no exception.

packages are an important feature of Go

packages define a unit of compiled code and their names help provide a level of indirection to the identifiers that are declared inside of them, just like a namespace. This makes it possible to distinguish identifiers that are declared with exactly the same name in the different packages you import.

Imports are just that: they import code and give you access to identifiers such as types,
functions, constants, and interfaces.

All code files in a folder must use the same package name, and it’s common prac-
tice to name the package after the folder. As stated before, a package defines a unit of
compiled code, and each unit of code represents a package.

each code file will contain the keyword package at the top with a name
for the package. e.g. Each code file in the "search" folder will contain "search" for the pack-
age name.

Imported packages can be grouped as:

import (
   "log"
   "os"
    _ "github.com/goinaction/code/chapter2/sample/matchers"
   "github.com/goinaction/code/chapter2/sample/search"
)

Packages from standard library don't need to have path specified.
Packages from the local workspace have to have their relative path specified (relative to the workspace).

When you import code from the standard library, you only need to reference the
name of the package, unlike when you import code from outside of the standard
library. The compiler will always look for the packages you import at the locations ref-
erenced by the GOROOT and GOPATH environment variables.

what should be the values of GOPATH and GOROOT?

import the matchers package and use the blank identifier (_) before listing out the import path.This is a technique in Go to allow initialization from a package to occur, even if you
don’t directly use any identifiers from the package. To make your programs more
readable, the Go compiler won’t let you declare a package to be imported if it’s not
used. The blank identifier allows the compiler to accept the import and call any init
functions that can be found in the different code files within that package.

All init functions in any code file that are part of the program will get called before
the main function.

When is the init() function run?

func init() {
  // Change the device for logging to stdout.
   log.SetOutput(os.Stdout)
   ...
}

This init function sets the logger from the standard library to
write to the stdout device. By default, the logger is set to write to the stderr device.

call to the Run function that belongs to the search package:
search.Run("president")

The log package provides support for logging messages to the stdout , stderr , or even
custom devices. The sync package provides support for synchronizing goroutines,

var matchers = make(map[string]Matcher)
This variable is located outside the scope of any function and so is considered a
package-level variable. The variable is declared using the keyword var and is declared
as a map of Matcher type values with a key of type string .

the name of the variable matchers starts with a lowercase letter.

In Go, identifiers are either exported or unexported from a package.

  • An exported identifier can be directly accessed by code in other packages when the respective package is imported. These identifiers start with a capital letter.
  • Unexported identifiers start with a lowercase letter and can’t be directly accessed by code in other packages. But just because an identifier is unexported, it doesn’t mean other packages can’t indirectly access these identifiers. As an example, a function can return a value of an unexported type and this value is accessible by any calling function, even if the calling function has been declared in a different package.


This variable declaration also contains an initialization of the variable via the
assignment operator and a special built-in function called make .

A map is a reference type that you’re required to make in Go. If you don’t make the
map first and assign it to your variable, you’ll receive errors when you try to use the map
variable. This is because the zero value for a map variable is nil .

In Go, all variables are initialized to their zero value. For numeric types, that value
is 0 ; for strings it’s an empty string; for Booleans it’s false ; and for pointers, the zero
value is nil . When it comes to reference types, there are underlying data structures
that are initialized to their zero values. But variables declared as a reference type set to
their zero value will return the value of nil .

Go programs can be structured to handle the launching and syn-
chronization of goroutines that run concurrently

To declare a function in Go, use the keyword func followed by the function name, any
parameters, and then any return values.

feeds, err := RetrieveFeeds()
if err != nil {
   log.Fatal(err)
}

NOTE: You can omit the parentheses () from an if statement in Golang, but the curly braces {} are mandatory!

This function belongs to the search package and returns two values. The first return value is a slice
of Feed type values. A slice is a reference type that implements a dynamic array. You use
slices in Go to work with lists of data.

The second return value is an error.

functions can have multiple return
values. It’s common to declare functions that return a value and an error value just
like the RetrieveFeeds function. If an error occurs, never trust the other values being
returned from the function. They should always be ignored, or else you run the risk of
the code generating more errors or panics.

the short variable declaration operator ( := ). This operator is
used to both declare and initialize variables at the same time. The type of each value
being returned is used by the compiler to determine the type for each variable,
respectively. The short variable declaration operator is just a shortcut to streamline
your code and make the code more readable. The variable it declares is no different
than any other variable you may declare when using the keyword var .

results := make(chan *Result)

we use the built-in function make to create an unbuffered channel. We use
the short variable declaration operator to declare and initialize the channel variable
with the call to make . A good rule of thumb when declaring variables is to use the key-
word var when declaring variables that will be initialized to their zero value, and to
use the short variable declaration operator when you’re providing extra initialization
or making a function call.

Channels are also a reference type in Go like maps and slices, but channels imple-
ment a queue of typed values that are used to communicate data between goroutines.
Channels provide inherent synchronization mechanisms to make communication
safe.


The next two lines of code are used later to prevent the program from terminating
before all the search processing is complete.

// Setup a wait group so we can process all the feeds.
var waitGroup sync.WaitGroup
// Set the number of goroutines we need to wait for while
// they process the individual feeds.
waitGroup.Add(len(feeds))


In Go, once the main function returns, the program terminates. Any goroutines that
were launched and are still running at this time will also be terminated by the Go run-
time. When you write concurrent programs, it’s best to cleanly terminate any gorou-
tines that were launched prior to letting the main function return. Writing programs
that can cleanly start and shut down helps reduce bugs and prevents resources from
corruption.

Our program is using a WaitGroup from the sync package to track all the goroutines we’re going to launch. A WaitGroup is a great way to track when a goroutine is
finished performing its work. A WaitGroup is a counting semaphore, and we’ll use it to
count off goroutines as they finish their work.

On line 23 we declare a variable of type WaitGroup from the sync package. Then
on line 27 we set the value of the WaitGroup variable to match the number of gorou-
tines we’re going to launch. As you’ll soon see, we’ll process each feed concurrently
with its own goroutine. As each goroutine completes its work, it will decrement the

count of the WaitGroup variable, and once the variable gets to zero, we’ll know all the
work is done.


for _, item := range items {
   ...
}

range (keyword)

  • can be used with arrays, strings, slices, maps, and channels

for range

  • used to iterate over the slice of items
  • When used to iterate over a slice, we get two values back on each iteration:
    • index position of the element we’re iterating over
    • a copy of the value in that element

blank identifier (_)

  • used as a substitution for the variable that would be assigned to the index value for the range call. When you have a function that returns multiple values, and you don’t have a need for one, you can use the blank identifier to ignore those values. In our case with this range, we won’t be using the index value, so the blank identifier allows us to ignore it.


matcher, exists := matchers[feed.Type]
if !exists {
matcher = matchers["default"]
}

we check the map for a
key that matches the feed type. When looking up a key in a map, you have two
options: you can assign a single variable or two variables for the lookup call. The first
variable is always the value returned for the key lookup, and the second value, if speci-
fied, is a Boolean flag that reports whether the key exists or not. When a key doesn’t
exist, the map will return the zero value for the type of value being stored in the map.
When the key does exist, the map will return a copy of the value for that key.

// Launch the goroutine
go func(matcher Matcher, feed *Feed) {
   Match(matcher, feed, searchTerm, results) 
   waitGroup.Done()
}(matcher, feed)


goroutine

  • light-weight process that is automatically time-sliced onto one or more operating system threads by the Go runtime.
  • a function that’s launched to run independently from other functions in the program.
  • Use the keyword go to launch and schedule goroutines to run concurrently. 
  • can be an anonymous function
  • can be launched in a (for range) loop, for each element of some set: this allows each element to be processed independently in a concurrent fashion
anonymous function

  • a function that’s declared without a name
  • can take parameters

pointer variables

  • are great for sharing variables between functions. They allow functions to access and change the state of a variable that was declared within the scope of a different function and possibly a different goroutine.
  • In Go, all variables are passed by value. Since the value of a pointer variable is the address to the memory being pointed to, passing pointer variables between functions is still considered a pass by value.


waitGroup.Done()

Once the main task withing the goroutine completes, we execute the code which decrements the WaitGroup count. Once every goroutine finishes calling Done method, the program will know every main task has been done (e.g. element has been processed).

There’s something else interesting about the method call to Done: the WaitGroup
value was never passed into the anonymous function as a parameter, yet the anony-
mous function has access to it. Go supports closures and you’re seeing this in action. In fact, the searchTerm and results variables are also being accessed by the anonymous function via closures.
Thanks to closures, the function can access those variables directly without the need to
pass them in as parameters. The anonymous function isn’t given a copy of these variables; it has direct access to the same variables declared in the scope of the outer function. This is the reason why we don’t use closures for the matcher and feed variables.

---

With all the processing goroutines working, sending results on the results channel
and decrementing the waitGroup counter, we need a way to display those results and
keep the main function alive until all the processing is done. We'll launch yet another anonymous function as a goroutine. This anonymous function takes no parameters and uses closures to access both the waitGroup and results variables. This goroutine calls the method Wait() on the WaitGroup value, which is causing the goroutine to block until the count for the WaitGroup hits zero. Once that happens, the goroutine calls the built-in function close on the channel, which as you’ll see causes the program to terminate.


// Launch a goroutine to monitor when all the work is done.
go func() {
   // Wait for everything to be processed.
   waitGroup.Wait()

   // Close the channel to signal to the Display

   // function that we can exit the program.
   close(results)
}()

---

func Match(matcher Matcher, feed *Feed, searchTerm string, results chan<- *Result) {
   // Perform the search against the specified matcher.
   searchResults, err := matcher.Search(feed, searchTerm)
   if err != nil {
      log.Println(err)
      return
   }
   // Write the results to the channel.
   for _, result := range searchResults {
      results <- result
   }
}

results are written to the channel

BK: not how nil is used instead of null
BK: note how it's so convenient the model of returning function result and error at the same time; no need to pass variable by pointer and no expensive exceptions
BK: note how there are no brackets around conditions in if, for... statements.

---

Variables


Variable names can't start with number.

---

Constants


The Go Blog - Constants

"Hello, 世界" is untyped string constant.
It remains an untyped string constant even when given a name:

const hello = "Hello, 世界"

hello is also an untyped string constant.

An untyped constant is just a value, one not yet given a defined type that would force it to obey the strict rules that prevent combining differently typed values.


typed string constant is one that's been given a type:

const typedHello string = "Hello, 世界"



---

Functions

Go by Example: Functions

func plus(a int, b int) int {...}

Go by Example: Variadic Functions

func sum(nums... int){...}

Specifying function's default value for an argument is NOT supported.
Default value in Go's method

Data Types

How to find a type of an object in Go?

import "reflect"
tst := "string"
fmt.Println(reflect.TypeOf(tst))


A Tour of Go - Type switches

switch v := i.(type) {
case T:
    // here v has type T
case S:
    // here v has type S
default:
    // no match; here v has the same type as i
}

Type assertions

---
type is reserved word in Go and can't be used as e.g. struct field name (Go linter issues error: syntax error: unexpected type, expecting field name or embedded type)

What (exactly) does the type keyword do in go?
---

String 

How do you write multiline strings in Go?

This raw quote (raw literal) does not parse escape sequences (\n would remain):

`line 1
line 2\n
line 3`

It is possible to use formatters though:

fmt.Sprintf(`a = %d`, 123)

Another option:

"line 1" +
"line 2" +
"line 3"




What is the difference between backticks (``) & double quotes (“”) in golang?

String Comparison - use == or !=

Slice string into letters

String Formatting 


s := fmt.Sprintf("a %s", "string")

Go by Example: String Formatting

The empty interface


interface{}

  • interface type that specifies zero methods
  • may hold values of any type
  • used by code that handles values of unknown type

var i interface{}
i = 42
i = "hello"

A Tour of Go - The empty interface



package main

import (
"fmt"
)

func main() {
var i interface{}
var j interface{} = 2
var k *interface{}
i = &j
k = &j
fmt.Println(i)
        
        // invalid indirect of i (type interface {})
// fmt.Println(*i) 

fmt.Println(*k)

}

Output:

0x40c130
2


Array


  • collection of elements of a single type
  • a fixed-length data type that contains a contiguous block of elements of the same type


var intArray [5]int
intArray[0] = 10
var intArray = [5]int {10, 20, 30}
var intArray = [5]int {0:10, 2:30, 4:50}
intArray := [5]int {10, 20, 30, 40, 50}
intArray := [...]int {10, 20, 30, 40, 50}

Create array of array literal in Golang

a := [][]int{{1,2,3},{4,5,6}}





Slice


  • a segment of dynamic arrays that can grow and shrink
  • indexable and have a length
  • used as a dynamic array - when we want to use an array but don't know its size in advance


var numbers []int
or
numbers := make([]int, 0)

numbers = append(numbers, 1)
numbers = append(numbers, 2)
fmt.Println(len(numbers)) // == 2


Go Slices: usage and internals


Declare slice or make slice?

var s []int
  • simple declaration
  • crates so called "nil slice"
  • does not allocate memory
  • s points to nil
  • should not be a return value of an API which returns slice (an empty slice should be returned)
  • marshaling the nil slice (var s []int) will produce null

s  := make([]int, 0)
  • creates so called "empty slice"
  • allocates memory
  • s points to memory to a slice with 0 elements
  • should be returned if an API needs to return a slice with 0 elements
  • marshalling the empty slice will produce the expected []


Convert slice of string to slice of pointer to string

Convert slice of type A to slice of pointers to type A

This:

for _, v := range a {
b = append(b, &v)
}

and this:

for i := 0; i < len(a); i++ {
b = append(b, &a[i])
}

are not the same. In the latter, you are taking the address of element a[i] in the array (which is what you want). In the former, you are taking the address of the iteration variable v, which, as you discovered, does not change during the loop execution (it gets allocated once, it's in a completely new location in memory, and gets overwritten at each iteration).

BK: We can still use range:

 for i := range a {
b = append(b, &a[i])
}

---
How to declare a slice of slices (2-D slice)?


slice literal is written as []type{<value 1>, <value 2>, ... }.

A slice of ints would be []int{1,2,3}
A slice of int slices would be [][]int{{1,2,3}, {4,5,6}}

var s2d [][]string = [][]string{{"a", "b", "c"}, {"d", "e", "f"}}

Try it in The Go Playground


---

Interfaces

Struct implements interface if it implements all its methods.


pinger/pinger.go:

package pinger

type (
   PingerConfig struct {
      timeout int
   }

   Pinger interface {
      Ping(ip string) error
   }

   // New is a Pinger factory method
   // New func(pingerConfig PingerConfig) (Pinger, error)
)

superPinger/pinger.go:

package superpinger

import (
   "example.com/myproduct/myproject/internal/pkg/pinger"
)

type superPinger struct {
id     string
}

// New function creates an instance of PostgreSQL client
func New(config pinger.PingerConfig) (pinger.Pinger, error) {
        superPinger := superPinger(config)
        err := superPinger.Init(...)
return superPinger, err
}


// Ping function verifies remote endpoint accessibility
func (superPinger superPinger) Ping(ip string) error {
err := doPing(ip)
return err
}

main.go:

import (
   "example.com/myproduct/myproject/internal/pkg/pinger"
   "example.com/myproduct/myproject/internal/pkg/superpinger"
)

...
pingerConfig := pinger.NewPingerConfig(...)
pinger, err := superpinger.New(pingerConfig)
pinger.Ping("8.8.8.8")
...

---


Concurrency & Parallelism


How can my Go program keep all the CPU cores busy?


---


Packages

If we have:

import "mypackage"

then we need to use package name when calling any its exported member:

mypackage.Foo()


Internal Packages


https://notes.shichao.io/gopl/ch10/#internal-packages


fmt


fmt.Println("Table names:", tableNames)

SPACE character is automatically inserted between these two strings.

Golang - How to print the values of Arrays?

fmt.Printf("%v", projects)


fmt.Printf


%+v - prints struct’s field names (if value is a struct)

---

encoding/json


Parsing JSON in Golang

the Species attribute in our Bird struct will map to the species, or Species or sPeCiEs JSON property.

Go by Example: JSON

When defining a structure into which we want to unmarshal some JSON, we have to declare struct members as exported (their names have to start with capital letter). This is required so other package (json) can use reflection and access these fields.

JSON and dealing with unexported fields

The json library does not have the power to view fields using reflect unless they are exported. A package can only view the unexported fields of types within its own package.


It's fundamentally limited by the reflect package that any package can't set unexported fields in types
defined in other packages (without using unsafe.)

---
How to unmarshal an escaped JSON string in Go?
strconv.Unquote()
---



---

Go CLI



$ go
Go is a tool for managing Go source code.

Usage:

        go <command> [arguments]

The commands are:

        bug         start a bug report
        build       compile packages and dependencies
        clean       remove object files and cached files
        doc         show documentation for package or symbol
        env         print Go environment information
        fix         update packages to use new APIs
        fmt         gofmt (reformat) package sources
        generate    generate Go files by processing source
        get         download and install packages and dependencies
        install     compile and install packages and dependencies
        list        list packages or modules
        mod         module maintenance
        run         compile and run Go program
        test        test packages
        tool        run specified go tool
        version     print Go version
        vet         report likely mistakes in packages

Use "go help <command>" for more information about a command.

Additional help topics:

        buildmode   build modes
        c           calling between Go and C
        cache       build and test caching
        environment environment variables
        filetype    file types
        go.mod      the go.mod file
        gopath      GOPATH environment variable
        gopath-get  legacy GOPATH go get
        goproxy     module proxy protocol
        importpath  import path syntax
        modules     modules, module versions, and more
        module-get  module-aware go get
        packages    package lists and patterns
        testflag    testing flags
        testfunc    testing functions

Use "go help <topic>" for more information about that topic.


go build


$ go help build
usage: go build [-o output] [-i] [build flags] [packages]

Build compiles the packages named by the import paths,
along with their dependencies, but it does not install the results.

If the arguments to build are a list of .go files, build treats
them as a list of source files specifying a single package.

When compiling a single main package, build writes
the resulting executable to an output file named after
the first source file ('go build ed.go rx.go' writes 'ed' or 'ed.exe') or the source code directory ('go build unix/sam' writes 'sam' or 'sam.exe'). The '.exe' suffix is added when writing a Windows executable.

When compiling multiple packages or a single non-main package,
build compiles the packages but discards the resulting object,
serving only as a check that the packages can be built.

When compiling packages, build ignores files that end in '_test.go'.

The -o flag, only allowed when compiling a single package,
forces build to write the resulting executable or object
to the named output file, instead of the default behavior described
in the last two paragraphs.

The -i flag installs the packages that are dependencies of the target.

The build flags are shared by the build, clean, get, install, list, run, and test commands:

        -a
                force rebuilding of packages that are already up-to-date.
        -n
                print the commands but do not run them.
        -p n
                the number of programs, such as build commands or
                test binaries, that can be run in parallel.
                The default is the number of CPUs available.
        -race
                enable data race detection.
                Supported only on linux/amd64, freebsd/amd64, darwin/amd64 and windows/amd64.
        -msan
                enable interoperation with memory sanitizer.
                Supported only on linux/amd64, linux/arm64
                and only with Clang/LLVM as the host C compiler.
        -v
                print the names of packages as they are compiled.
        -work
                print the name of the temporary work directory and
                do not delete it when exiting.
        -x
                print the commands.

        -asmflags '[pattern=]arg list'
                arguments to pass on each go tool asm invocation.
        -buildmode mode
                build mode to use. See 'go help buildmode' for more.
        -compiler name
                name of compiler to use, as in runtime.Compiler (gccgo or gc).
        -gccgoflags '[pattern=]arg list'
                arguments to pass on each gccgo compiler/linker invocation.
        -gcflags '[pattern=]arg list'
                arguments to pass on each go tool compile invocation.
        -installsuffix suffix
                a suffix to use in the name of the package installation directory,
                in order to keep output separate from default builds.
                If using the -race flag, the install suffix is automatically set to race
                or, if set explicitly, has _race appended to it. Likewise for the -msan
                flag. Using a -buildmode option that requires non-default compile flags
                has a similar effect.
        -ldflags '[pattern=]arg list'
                arguments to pass on each go tool link invocation.
        -linkshared
                link against shared libraries previously created with
                -buildmode=shared.
        -mod mode
                module download mode to use: readonly or vendor.
                See 'go help modules' for more.
        -pkgdir dir
                install and load all packages from dir instead of the usual locations.
                For example, when building with a non-standard configuration,
                use -pkgdir to keep generated packages in a separate location.
        -tags 'tag list'
                a space-separated list of build tags to consider satisfied during the
                build. For more information about build tags, see the description of
                build constraints in the documentation for the go/build package.
        -toolexec 'cmd args'
                a program to use to invoke toolchain programs like vet and asm.
                For example, instead of running asm, the go command will run
                'cmd args /path/to/asm <arguments for asm>'.

The -asmflags, -gccgoflags, -gcflags, and -ldflags flags accept a
space-separated list of arguments to pass to an underlying tool
during the build. To embed spaces in an element in the list, surround it with either single or double quotes. The argument list may be receded by a package pattern and an equal sign, which restricts the use of that argument list to the building of packages matching that pattern (see 'go help packages' for a description of package patterns). Without a pattern, the argument list applies only to the packages named on the command line. The flags may be repeated
with different patterns in order to specify different arguments for
different sets of packages. If a package matches patterns given in
multiple flags, the latest match on the command line wins.
For example, 'go build -gcflags=-S fmt' prints the disassembly
only for package fmt, while 'go build -gcflags=all=-S fmt'
prints the disassembly for fmt and all its dependencies.

For more about specifying packages, see 'go help packages'.
For more about where packages and binaries are installed,
run 'go help gopath'.
For more about calling between Go and C/C++, run 'go help c'.

Note: Build adheres to certain conventions such as those described
by 'go help gopath'. Not all projects can follow these conventions,
however. Installations that have their own conventions or that use
a separate software build system may choose to use lower-level
invocations such as 'go tool compile' and 'go tool link' to avoid
some of the overheads and design decisions of the build tool.

See also: go install, go get, go clean.

Note that list of options goes BEFORE list of source code files.

$ go build -o build/wiki wiki.go 

To keep the flag package simple, the first non-flag is treated as the first command line argument, regardless of what might come after, so all flags must come before all regular arguments.

The go tool uses the flag package and so is subjected to the same limitations for it's built-in subcommands. Therefore the "output" flag must be set before the arguments (which contain the input).

example:
go build foo -o bar -> flags: {} args: [foo, -o, bar]
go build -o bar foo -> flags: {o: bar} args: [foo] 

[(How to) Give a name to the binary using go build]

go get



$ go help get
usage: go get [-d] [-f] [-t] [-u] [-v] [-fix] [-insecure] [build flags] [packages]

Get downloads the packages named by the import paths, along with their dependencies. It then installs the named packages, like 'go install'.

The -d flag instructs get to stop after downloading the packages; that is, it instructs get not to install the packages.

The -f flag, valid only when -u is set, forces get -u not to verify that each package has been checked out from the source control repository implied by its import path. This can be useful if the source is a local fork of the original.

The -fix flag instructs get to run the fix tool on the downloaded packages before resolving dependencies or building the code.

The -insecure flag permits fetching from repositories and resolving
custom domains using insecure schemes such as HTTP. Use with caution.

The -t flag instructs get to also download the packages required to build the tests for the specified packages.

The -u flag instructs get to use the network to update the named packages and their dependencies. By default, get uses the network to check out missing packages but does not use it to look for updates to existing packages.

The -v flag enables verbose progress and debug output.

Get also accepts build flags to control the installation. See 'go help build'.

When checking out a new package, get creates the target directory
GOPATH/src/<import-path>. If the GOPATH contains multiple entries,
get uses the first one. For more details see: 'go help gopath'.

When checking out or updating a package, get looks for a branch or tag that matches the locally installed version of Go. The most important rule is that if the local installation is running version "go1", get searches for a branch or tag named "go1". If no such version exists it retrieves the default branch of the package.

When go get checks out or updates a Git repository,
it also updates any git submodules referenced by the repository.

Get never checks out or updates code stored in vendor directories.

For more about specifying packages, see 'go help packages'.

For more about how 'go get' finds source code to download, see 'go help importpath'.

This text describes the behavior of get when using GOPATH
to manage source code and dependencies. If instead the go command is running in module-aware mode, the details of get's flags and effects change, as does 'go help get'. See 'go help modules' and 'go help module-get'.

See also: go build, go install, go clean.

Example:

$ go get -d -v ./...

What do three dots “./…” mean in Go command line invocations?

./ tells to start from the current folder, ... tells to go down recursively.

go install



$ go help install
usage: go install [-i] [build flags] [packages]

Install compiles and installs the packages named by the import paths.

The -i flag installs the dependencies of the named packages as well.

For more about the build flags, see 'go help build'.
For more about specifying packages, see 'go help packages'.

See also: go build, go get, go clean.

It:

  • places the executable file in $GOPATH/bin
  • caches all non-main packages (which app imports) in $GOPATH/pkg
    • Cache is used in the next compilation unless it changes in the meantime

Go naming convention

What are conventions for filenames in Go?

File names that begin with "." or "_" are ignored by the go tool
Files with the suffix _test.go are only compiled and run by the go test tool.
Files with os and architecture specific suffixes automatically follow those same constraints, e.g. name_linux.go will only build on linux, name_amd64.go will only build on amd64. This is the same as having a //+build amd64 line at the top of the file

filenames are generally all lowercase in case, both for consistency and for systems with case-insensitive filesystems

regular file names are lower case, short, and without any sort of underscore or space. Generally, file names follow the same convention as package names.

there is no convention but _ suffixes may have special semantics in the future so I recommend to avoid them

Naming a file dns_windows.go will cause it to be included only when building the package for Windows; similarly, math_386.s will be included only when building the package for 32-bit x86.

File name convention for compound words?

Source file names are usually kept short, so in your case I would tend to call it find.go in package weightedunion <--  the idea is to make better use of packages when you are tempted to name it long


What is the best naming convention of keeping source files in a programming language?

Go follows a convention where source files are all lower case with underscore separating multiple words. Example:

https://github.com/kubernetes/client-go/tree/master/discovery/cached/diskGolang


folder structure and filename conventions under clean architecture

Interfaces in Go have a er-suffix (io.Reader, fmt.Stringer, etc).

The filenames are not per se named after a single type as often the package contains several types (see your first question).

Mixed case filenames are cute until your filesystem does not distinguish cases. Keep it simple, lowercase only.

Style guideline for Go packages


Go code Documentation


Godoc: documenting Go code

Go & Docker


Deploying a Go Application in a Docker Container

To document a type, variable, constant, function, or even a package, write a regular comment directly preceding its declaration, with no intervening blank line. Godoc will then present that comment as text alongside the item it documents.

Comment is a complete sentence that begins with the name of the element it describes.

Go & PostgreSQL


Go comes with embedded database/sql package.
The standard PostgreSQL DB driver for Go is lib/pq.

package pq

How to use PostgreSQL

Querying for a single record using Go's database/sql package

QueryRow() is a method provided by the DB type and is used to execute an SQL query that is expected to return a single row.

Resources:


"Go in Action" by William Kennedy