> For the complete documentation index, see [llms.txt](https://benhurott.gitbook.io/appsecben/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://benhurott.gitbook.io/appsecben/golang/cheat-sheet.md).

# Cheat Sheet

### Naming Convention

Thanks to: <https://medium.com/@kdnotes/golang-naming-rules-and-conventions-8efeecd23b68>

#### **Files**

1. Go follows a convention where source files are all lower case with underscore separating multiple words.
2. Compound file names are separated with \_
3. File names that begin with “.” or “\_” are ignored by the go tool
4. Files with the suffix `_test.go` are only compiled and run by the `go test` tool.

#### **Functions**

The case defines if it will be public or private for the package.

* Private: `func writeToDb(){}`
* Public: `func WriteToDb(){}`

The same for `struct properties`.

#### Constants

Constant should use all capital letters and use underscore `_` to separate words.\
Ex: `const CONNECTION_URL := "...."`

#### Variables

1. Generally, use a relatively simple (short) name.
2. Consistent naming style should be used the entire source code

`user` to `u`

`userID` to `uid`

* If variable type is `bool`, its name should start with `Has`, `Is`, `Can` or `Allow`, etc.
* A single letter represents index: `i, j, k`

### Variables

```go
// DECLARATIONS
var name string
name = "Thor"

name := "Thor"

// ARRAYS
var numbers [3]int
numbers[0] = 1

// SLICES
numbers := []int{}
numbers = append(numbers, 2)
```

### IF

```go
name := "thor"

if name == "thor" {
	
} else if name == "odin" {

} else {
	
}
```

### FOR

```go
names := []string{
	"Thor", "Odin", "Loki",
}

for i := 0; i < len(names); i++ {
	fmt.Println(i, ":", names[i])
}

for i, v := range names {
	fmt.Println(i, ":", v)
}
```

### SWITCH

```go
switch os := runtime.GOOS; os {
case "darwin":
	fmt.Println("OS X.")
case "linux":
	fmt.Println("Linux.")
default:
	// freebsd, openbsd,
	// plan9, windows...
	fmt.Printf("%s.\n", os)
}
```

### FUNCTION

```go
func simple() {
	fmt.Println("simple function")
}

func withReturnValue() string {
	return "Function with return value"
}

func withArgs(myArg string) {
	fmt.Println(myArg)
}

func withMultipleArgs(myList ...string) {
	// withMultipleArgs("Val1", "Val2", "ValN")
}

func withToupleResult() (value int, err error) {
	// value, err = withToupleResult()
	return 1, nil
}
```

```go
// FUNCTION AS PARAMETER
type Fn func()

func onError(handler Fn) {
	handler()
}
```

### Folders

```go
package main

import (
    "log"
    "os"
)

func main() {
    // Create a folder/directory at a full qualified path
    err := os.Mkdir("/Users/temp", 0755)
    if err != nil {
        log.Fatal(err)
    }

    // Create a folder recursively
    err := os.MkdirAll(dirPath, 0755)
	  if err != nil {
		    log.Fatal(err)
    }
    
    // Get current dir
    currentDirPath, err := os.Getwd()
}
```

### Read File

```go
content, _ := ioutil.ReadFile("list.txt")
fmt.Println(string(content))
```

### Write File

```go
fileName := "new-file.txt"

flags := os.O_WRONLY | os.O_CREATE | os.O_APPEND
file, _ := os.OpenFile(fileName, flags, 0666)

file.WriteString("This is a new file")
file.Close()
```

### Error Handling

```go
package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"strings"
)

func main() {
	fileName := "list.txt"

	file, err := os.Open(fileName)
	handleError(err)

	reader := bufio.NewReader(file)

	var lines []string

	closeFile := func() {
		file.Close()
	}

	for {
		line, err := reader.ReadString('\n')
		if err == io.EOF {
			closeFile()
			break
		}
		handleErrorWithCallback(err, closeFile)
		line = strings.TrimSpace(line)
		lines = append(lines, line)
	}

	fmt.Println(lines)
}

type ErrorHandlerCallback func()

func handleError(err error) {
	if err != nil {
		panic(err)
	}
}

func handleErrorWithCallback(err error, handler ErrorHandlerCallback) {
	if err != nil {
		handler()
		panic(err)
	}
}

```

### Date and Time

Time Format: <https://golang.org/src/time/format.go>

```go
package main

import (
	"fmt"
	"time"
)

func main() {
	// dd/mm/yyyy hh:mm:ss
	now := time.Now().Format("02/01/2006 15:04:05")
	fmt.Println(now)
}

```

### Structs

```go
type User struct {
	email    string
	password string
	enabled  bool
}

// adding a Disable function to a user instance
func (u *User) Disable() {
	u.enabled = false
}

func main() {

	admin := User{
		email:    "admin@admin.com",
		password: "Admin123",
		enabled:  true,
	}

	guest := new(User)
	guest.email = "guest@guest.com"
}
```

### Creating Packages

```go
//
// playground/user/user.go
//
package user

type User struct {
	Email    string
	Password string
	Enabled  bool
}

func (u *User) Disable() {
	u.Enabled = false
}


//
// playground/main.go
//
package main

import (
	"fmt"
	"playground/user"
)

func main() {
	admin := user.User{
		Email:    "admin@admin.com",
		Password: "Admin123",
		Enabled:  true,
	}

	fmt.Println(admin)
}

```

### Pointers

```go
// CODE SAMPLE
package main

import "fmt"

func main() {
	user := User{Enabled: true}
	fmt.Println(user)

	disableUser(user)
	fmt.Println(user)
}

type User struct {
	Enabled bool
}

func disableUser(user User) {
	user.Enabled = false
}

// OUTPUT
{true}
{true}

/*
	This will not change the user because the function
	disableUser is recieving a user as a value, not
	a pointer to the same user in memory.
	To change the original object, we need do two things:
	
	1. Change the function to receive a pointer.
	2. Call the function sending the pointer.
	
	And here is the magic words:
	- Use * to receive a pointer
	- Use & to send a pointer
*/
func main() {
	user := User{Enabled: true}
	fmt.Println(user)

	disableUser(&user) // <=== HERE
	fmt.Println(user)
}

type User struct {
	Enabled bool
}

func disableUser(user *User /* <=== HERE*/) {
	user.Enabled = false
}

// OUTPUT NOW
{true}
{false}
```

### Interfaces

```go
func main() {
	user := User{Status: ACTIVE}
	fmt.Println(user)
	setStatus(&user, INACTIVE)
	fmt.Println(user)
}

type Status int

const (
	ACTIVE Status = iota
	INACTIVE
	DELETED
)

/*
	An interface define all methods an struct needs to
	implement to be compliance with the definition.
*/
type WithStatus interface {
	SetStatus(status Status)
}

func setStatus(entity WithStatus, status Status) {
	entity.SetStatus(status)
}


/*
	If we want to pass a user instance to the setStatus func,
	the User struct must implement all the methods the
	WithStatus interface require.
*/
type User struct {
	Status Status
}

func (user *User) SetStatus(status Status) {
	user.Status = status
}


```

### Enum

```go
type Status int

const (
	ACTIVE Status = iota
	INACTIVE
	DELETED
)
```

### WaitGroup

```go
/*
	When the application runs multiple functions
	in background, if you want to deal with the
	concurrence and know when is finish, use the
	WaitGroup from sync package.
*/

package main

import (
	"fmt"
	"sync"
)

var wg sync.WaitGroup // create the group

func main() {
	wg.Add(1) // indicating a new work will be add
	go say("Hi")
	wg.Wait() // wait until all the work done
}

func say(text string) {
	fmt.Printf(text)
	wg.Done() // mark a work for done
}
```

### Defer

```go
/*
	When we want to run something after the function finishes
	(even for an error, for example), we can use defer.
*/
package main

import (
	"fmt"
)

func main() {
	defer finish()
	fmt.Println("Enf of main")
}

func finish() {
	fmt.Println("We are done!")
}

/*
	=== OUTPUT ===
	Enf of main
  We are done!
*/
```

### Panic and Recover

```go
/*
	When something goes wrong and a panic is raise, 
	has a function that you can call and prevent the
	software to stop work.
	Its called recover.
*/

package main

import (
	"fmt"
)

func main() {
	defer finish()
	defer cleanup()
	fmt.Println("Enf of main")
	panic("fuuuuuuck") // <=== it should kill the program, right?
}

func cleanup() {
	if r := recover(); r != nil { // <=== but here we are recovering =)
		fmt.Println("recover: ", r)
	}
}

func finish() {
	fmt.Println("We are done!")
}

```

### Channels and Concurrency

Channels are the pipes that connect concurrent goroutines. You can send values into channels from one goroutine and receive those values into another goroutine.

Youtube:

* <https://www.youtube.com/watch?v=LvgVSSpwND8>

```go
package main

import (
	"fmt"
)

func main() {
	channel := make(chan int)

	go sum(channel, 5, 8)

	result := <-channel

	close(channel) // close the channel after no more work needed

	fmt.Println(result)
}

func sum(c chan int, a int, b int) {
	c <- a + b
}
```

### Unit Test

```go
// my_file_test.go
package my_package

import "testing"

func TestCrawler(t *testing.T) {
	result := my_func()
	
	if result == nil {
		t.Error("Ooops! This is the error message") // to indicate test failed
	}
}
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://benhurott.gitbook.io/appsecben/golang/cheat-sheet.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
