x509: certificate signed by unknown authority

I have built a Docker container with a Go application that used the Go AWS SDK. When my program tried to access an S3 bucket I got the error message

RequestError: send request failed
caused by: Get https://MY_BUCKET_NAME.s3.amazonaws.com: x509: certificate signed by unknown authority

To solve the problem I had to add the following line to the Dockerfile

On Ubuntu

RUN apt ca-certificates && rm -rf /var/cache/apk/*

On Alpine

RUN apk update && apk add ca-certificates && rm -rf /var/cache/apk/* 

Docker for Windows cannot start: “Hardware assisted virtualization and data execution protection must be enabled in the BIOS”

To start Docker on Windows, Hyper-V and the Hypervisor has to be enabled on Windows.

  1. Start a PowerShell window as administrator
  2. Enable Hyper-V
    dism.exe /Online /Enable-Feature:Microsoft-Hyper-V /All
  3. Enable the Hypervisor
    bcdedit /set hypervisorlaunchtype auto
  4. Restart the computer

List the Active Directory groups the user is a member of

To list the Active Directory groups where the current user is a member, execute in the PowerShell window

(New-Object System.DirectoryServices.DirectorySearcher("(&(objectCategory=User)(samAccountName=$($env:username)))")).FindOne().GetDirectoryEntry().memberOf

To get the Active Directory groups for another user, replace THE_USER_NAME with the Active directory user name of the person.

(New-Object System.DirectoryServices.DirectorySearcher("(&(objectCategory=User)(samAccountName=THE_USER_NAME))")).FindOne().GetDirectoryEntry().memberOf

Debugging Go programs in Atom

To be able to debug Go programs in Atom, make sure the Go IDE is installed. See Install the Go IDE at Install and set up Go

To start debugging select the Debugger tab in the upper right corner of Atom

If you get the error message: The debugger is not attached, and when you click Attach debugger you get the error message: No debuggers installed, look for available debuggers on atom.io/packages

Check if the go-debug Atom package is installed

  • Open the Settings page from the File menu
  • Select Install on the left side
  • Search for go-debug
  • If the package is not installed, click the Install button

If you still get the same error message, download the go-delve package.

Visit https://github.com/derekparker/delve/tree/master/Documentation/installation for more info.

  • In the terminal window execute
    go get -u github.com/go-delve/delve/cmd/dlv
  • Restart Atom for the change to take effect.

 To debug your Go application

  • Click the Debugger tab in the upper right corner, and select the Debug config
  • To set a breakpoint, click the line in the program and press the F9 key. A red circle appears on the margin. 
  • The breakpoint appears on the right side of the screen too
  • Press F5 to run the application in the debugger
  • When the breakpoint is hit the toolbar on the right side shows the Stacktrace and the Variables. Click the arrow to open the section.
  • Click the arrow next to the variable name to show more details

Using Go packages

To use a public package in your Go application add the line to the top of your program to import the package

import "github.com/aws/aws-sdk-go/service/s3"

If this is the first time you are using the package, the error message appears in the output window of Atom when you save the file

cannot find package “github.com/aws/aws-sdk-go/service/s3” in any of:

C:\Go\src\github.com\aws\aws-sdk-go\service\s3 (from $GOROOT) C:\Users\MY_USERNAME\go\src\github.com\aws\aws-sdk-go\service\s3 (from $GOPATH)

Open a terminal window and execute the command to download the package

go get github.com/aws/aws-sdk-go/service/s3

 

Your first Go application

Programming in GO is quick and fun. You can write a working, compiled application with a few lines of code. In this example, we will use Visual Studio Code to edit the source code, and we have already configured it to start from the command line with the “code” command.

Write your first Go application

Create a directory for your application, let’s call it myapp

mkdir myapp

Open a terminal window in the myapp directory

cd myapp

Initialize the Go Modules. Go modules are available since Go version  1.11, in Go version 1.13 is the default over $GOPATH. In the main directory of your application execute

go mod init github.com/MY_USER_NAME/myapp

When we add an import statement to the code, Go will automatically update the go.mod file to include the dependency with the latest stable version. To list the referenced modules execute

go list -m all

Create a file for your module. This file is not required, but as it is on the top level, the package name is considered to be the name of the module.

code config.go

Enter to code

package myapp

func Config() string {
	return "Application config"
}

Create a sub-directory for the entry point of your application. When someone imports your application as a module this will be the command to execute.

mkdir -p cmd/myapp

Create the file for the command

code cmd/myapp/myapp.go

Create the main function

package main

import (
	"fmt"

	"github.com/MY_USER_NAME/myapp"
)

func main() {
	fmt.Println(myapp.Config())
}

Save the files and run the application

go run cmd/myapp/*

The output should be

Application config

Add a package to the application

mkdir mypackage

Create the package file

code mypackage/mypackage.go

Write the code of the package

package mypackage

func RunMyPackage() string {
	return "MyPackage running"
}

Update the main function to call the new package

code cmd/myapp/myapp.go

Add two lines to the code

package main

import (
	"fmt"

	"github.com/MY_USER_NAME/myapp"
	"github.com/MY_USER_NAME/myapp/mypackage" // NEW LINE
)

func main() {
	fmt.Println(myapp.Config())
	fmt.Println(mypackage.RunMyPackage()) // NEW LINE
}

Save the files and run the application. The output should be

go run cmd/myapp/*

Application config
MyPackage running





Using modules from other applications

To upgrade a module to the latest tagged version for example golang.org/x/text

go get golang.org/x/text

List all available versions of a module, for example, rsc.io/sampler

go list -m -versions rsc.io/sampler

Get a specific version of the module

go get rsc.io/sampler@v1.3.1

To remove unused dependencies from the go.mod and go.sum file

go mod tidy

Set directory access in Windows

When you use SetAccessRule() to set access rights on a Windows directory, the user who will get the permission has to be a member of the Administrators group. If the user is not a member of the Administrators group PowerShell shows the error message

Exception calling “SetAccessRule” with “1” argument(s): “Some or all identity references could not be translated.”

Go language notes

Differences between Go and the “C” type languages

Variable declaration

int i;        // C#
var i int = 5 // Go
i := 5 // Go

Function declaration

private int AddNumbers (int a, int b) {...}  // C#
func addNumbers(a int, b int) int {...} // Go

Loops

for

for (int i = 0; i < 5; i++) {...}  // C#
for i := 0; i < 5; i++ {...} // Go

while

// "while" loop in C#
int i = 0;
while (i < 5) {
i++;
}

// "while" loop in Go (the init and post statements are optional, so "for" can be used as "while")
i := 0
for i < 5 {
i++
}

infinite loop

while (true) {...}  // C#
for {...} // Go

if

if (a == b ) {... } // C#
if a == b {...}     // Go

switch

No “break” is needed after every “case”

defer

Wait with the function call until the surrounding function completes
deferred function calls are pushed into a last-in first-out stack

Arrays

var a [5]int   // Go (array with 5 integer elements)

Lists

Use “slices” with the “append” function to dynamically add elements to a slice and the underlying array.

Classes

There are no classes in Go, use “methods” that are functions with receivers (attributes). The receiver has to be specified in the same package as the function.

func (v MyStruct) MyFunction() int {...}

Use pointer receivers to modify the original reference of the receiver in the function.

func (v *MyStruct) MyFunction() int {
  v.X = 5
}

Functions with a receiver can take a value or pointer. It is recommended to use pointer receivers to be able to modify the passed-in argument and avoid copying it.

Private and public (exported) names

  • Exported (public) names start with an upper case letter
    math.Pi
  • Not exported (private) names start with lower case letter
    mypackage.private
  •  

Variables

  • When declaring variables, the name comes first, the type comes last
    var i int
  • We can declare multiple variables with the same type, and specify the type only once for the last one in one statement
    var a, b, c bool
  •  Inside functions the short variable variable declaration uses the implicit type
    d := 5
  •  We can declare and assign values to multiple variables with one statement
    e, f, g := true, false, "yes!"
  •  The basic types are
    bool

    string

    int (32 bit on 32 bit systems, 64 bit on 64 bit systems)
    int8 int16 int32 int64
    uint (32 bit on 32 bit systems, 64 bit on 64 bit systems)
    uint8 uint16 uint32 uint64
    uintptr (32 bit on 32 bit systems, 64 bit on 64 bit systems)

    byte // alias for uint8

    rune // alias for int32
    // represents a Unicode code point

    float32 float64

    complex64 complex128
  •  To print the type and value of a variable use %T and %v
    a := 8
    fmt.Printf("Type: %T Value: %v", a, a)
    Type: int Value 8
  •  Explicit type conversions with a NewType(value) syntax are required for assignments between different types
    var i int = 5
    var f float32 = float32(i)
  •  

Functions

  • If a function returns multiple values, enclose the return declaration in parentheses
    func myfunc(x, y string) (string, string) {
    return y, x
    }
  •  

Slices

 Dynamic view into an array. array[first:last+1] (the element specified by the second argument is not part of the slice)

var s []int = array[0:6]

Create a slice and the underlying array with “make([]type, length of the slice, capacity of the array)”

b := make([]int, 0, 5) // len(b)=0, cap(b)=5

To dynamically add elements to the slice and the underlying array use the “append” function

var s []int
s = append(s, 1)
// Appends an element with the value of 1 to the slice and the array

To iterate through an array or slice use the “for range” expression. It returns the index and the value of the current element

for i, v := range my_array{}

Maps

// key is string, value is integer (here we use "make" to create it)
m := make(map[string]int)

// key is string, value is a struct
type MyStruct struct {
x, y int
}
var m map[string]MyStruct

Install and set up Go

Set up the Go development environment

Install Git

Install the Go Programming Language

Test the Go installation

  • Open a new terminal window, so the new PATH settings are imported, and execute
go version

Download a remote sample package

To download the package, in a terminal window execute

go get github.com/golang/example/hello

Navigate to the directory of the downloaded application

cd ~/go/bin

To run the package, execute

hello

Install the Go IDE

The Atom editor is a great IDE for Go. To enable the IDE features in Atom

    • Start Atom
    • Open the settings window
      • On the Mac select the Preferences item in the Atom menu
      • On Windows select the Settings item in the File menu
  • On the left side select Install
  • Search for atom-ide-ui and install the package
  • Search for ide-go and install the package
  • Restart Atom

Install Git on Macintosh

  • Navigate to https://git-scm.com/download/mac to download Git for the Macintosh. The page automatically downloads the installer for the operating system you use.
  • This app is not trusted by Apple, so to install it
    • Control-click (right-click) the downloaded file and select Open
    • Click the Open button to confirm the action

Configure Git

To configure Git see Git configuration.