initial
This commit is contained in:
commit
74ae93a96e
10 changed files with 94691 additions and 0 deletions
263
joplin notion extension/Web Development/Go/Basics 2.md
Normal file
263
joplin notion extension/Web Development/Go/Basics 2.md
Normal file
|
|
@ -0,0 +1,263 @@
|
|||
Basics 2
|
||||
|
||||
Conditions
|
||||
|
||||
if/else if/else are same its just that brackets surrounding conditions are not required. switch case is similar too with extra functionality like multi case
|
||||
|
||||
```go
|
||||
func main() {
|
||||
day := 5
|
||||
|
||||
switch day {
|
||||
case 1,3,5:
|
||||
fmt.Println("Odd weekday")
|
||||
case 2,4:
|
||||
fmt.Println("Even weekday")
|
||||
case 6,7:
|
||||
fmt.Println("Weekend")
|
||||
default:
|
||||
fmt.Println("Invalid day of day number")
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### Loops
|
||||
like in other language. for iteraing over elements of arrays,slice and map range keyword can be used too. it gives index and value respectively.
|
||||
index may not be used so blank identifiers can be used which is like a black hole. And even if it is used then it means those values wont be used later so it will still generate error so in that case blank identifier can be used too
|
||||
|
||||
|
||||
```go
|
||||
adj := [2]string{"Big", "Tasty"}
|
||||
fruits := [...]string{"Apple", "Orange"}
|
||||
|
||||
for i := 0; i < len(adj); i++ {
|
||||
for j := 0; j < len(fruits); j++ {
|
||||
if adj[i] == "Big" {
|
||||
|
||||
fmt.Println("Big mentioned")
|
||||
}
|
||||
fmt.Println(adj[i], fruits[j])
|
||||
}
|
||||
}
|
||||
|
||||
for i, val := range adj {
|
||||
for j, val2 := range fruits {
|
||||
if val == "Big" {
|
||||
|
||||
fmt.Println("Big mentioned")
|
||||
}
|
||||
fmt.Println(val, val2)
|
||||
// blank identifers
|
||||
_, _ = i, j
|
||||
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Extras
|
||||
- go functions if needed to be used in other packages then it needed to be capitalized so using Run() instead of run().
|
||||
|
||||
|
||||
|
||||
random number
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand/v2"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Random integer between 0 and 99
|
||||
num := rand.IntN(100)
|
||||
fmt.Println("Integer (0-99):", num)
|
||||
|
||||
// Random float64 between 0.0 and 1.0
|
||||
floatNum := rand.Float64()
|
||||
fmt.Println("Float (0.0-1.0):", floatNum)
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
also
|
||||
```go
|
||||
|
||||
f,err := os.Open(path)
|
||||
|
||||
if err!=nil{
|
||||
return err
|
||||
}
|
||||
|
||||
defer f.Close()
|
||||
|
||||
scanner:= bufio.NewScanner(f)
|
||||
|
||||
|
||||
```
|
||||
NewScanner accepts io.Reader but os.Open outputs *os.File. due to inferfaces handled implicitly so need to 'implement interface' like in java
|
||||
|
||||
|
||||
|
||||
**structs**
|
||||
```go
|
||||
type Message struct {
|
||||
Id string `json:"id"`
|
||||
CreatedTimestamp int64 `json:"createdTimestamp"`
|
||||
Type int `json:"type"`
|
||||
Content string `json:"content"`
|
||||
Reference struct {
|
||||
MessageId string `json:"messageId"`
|
||||
} `json:"reference"`
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
or if null is expected and empty struct is not fine then simply use pointer struct
|
||||
```go
|
||||
type Message struct {
|
||||
Id string `json:"id"`
|
||||
CreatedTimestamp int64 `json:"createdTimestamp"`
|
||||
Type int `json:"type"`
|
||||
Content string `json:"content"`
|
||||
Reference *struct {
|
||||
MessageId string `json:"messageId"`
|
||||
} `json:"reference"`
|
||||
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
optional fields in struct
|
||||
|
||||
```go
|
||||
type User struct {
|
||||
Name string `json:"name"`
|
||||
Age *int `json:"age,omitempty"` // Optional
|
||||
Active *bool `json:"active,omitempty"` // Optional
|
||||
}
|
||||
```
|
||||
|
||||
for array of struct if we need to distinguish nil and empty slice before go 1.24 then
|
||||
```go
|
||||
Items *[]Product `json:"items,omitempty"`
|
||||
```
|
||||
|
||||
otherwise following will be fine
|
||||
```go
|
||||
Items []Product `json:"items,omitempty"`
|
||||
```
|
||||
|
||||
|
||||
parsing fields of multtiple types
|
||||
https://stackoverflow.com/questions/56394456/unmarshal-json-field-is-int-or-string
|
||||
|
||||
also
|
||||
https://go.dev/play/p/XnQRS8H0tKE
|
||||
```go
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func foo(x any) {
|
||||
switch v := x.(type) {
|
||||
case int:
|
||||
fmt.Printf("math: x + 2 == %d\n", v+2)
|
||||
case string:
|
||||
fmt.Printf("string: x + def == %s\n", v+"def")
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
var x any = 5
|
||||
foo(x)
|
||||
x = "abc"
|
||||
foo(x)
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
and maybe with reflects(not recommended)
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
func checkEquality(data any) {
|
||||
switch reflect.TypeOf(data).Kind() {
|
||||
case reflect.Int:
|
||||
if data == 1 {
|
||||
fmt.Println("It is equal to 1")
|
||||
} else {
|
||||
fmt.Println("It is not equal to 1")
|
||||
}
|
||||
case reflect.String:
|
||||
if data == "one" {
|
||||
fmt.Println("It is equal to one")
|
||||
} else {
|
||||
fmt.Println("It is not equal to one")
|
||||
}
|
||||
default:
|
||||
fmt.Println("Not a string nor an int")
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
checkEquality("one")
|
||||
checkEquality(1)
|
||||
checkEquality(true)
|
||||
checkEquality(34)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
**error handling**
|
||||
|
||||
|
||||
```go
|
||||
|
||||
err:= json.Unmarshal(data, &config)
|
||||
if err != nil {
|
||||
fmt.Println("Error in reading json")
|
||||
os.Exit(1)
|
||||
}
|
||||
```
|
||||
|
||||
short form of above
|
||||
```go
|
||||
if err:= json.Unmarshal(data, &config); err!=nil{
|
||||
// code for handling error
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
also for equivalent ry catch possibility
|
||||
|
||||
```go
|
||||
func riskyBlock() (err error) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
err = fmt.Errorf("recovered from panic: %v", r)
|
||||
}
|
||||
}()
|
||||
|
||||
// --- your code here ---
|
||||
x := 10 / 0 // panics
|
||||
fmt.Println(x) // never reached
|
||||
return nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
if err := riskyBlock(); err != nil {
|
||||
fmt.Println("Error:", err)
|
||||
}
|
||||
fmt.Println("Program continues")
|
||||
}
|
||||
```
|
||||
285
joplin notion extension/Web Development/Go/Basics.md
Normal file
285
joplin notion extension/Web Development/Go/Basics.md
Normal file
|
|
@ -0,0 +1,285 @@
|
|||
Basics
|
||||
|
||||
|
||||
datatypes
|
||||
|
||||
| Spec term | What it covers |
|
||||
|---|---|
|
||||
| **Basic types** (predeclared) | `bool`, `string`, numeric types (`int`, `uint`, `float`, `complex`, `byte`, `rune`) |
|
||||
| **Composite types** (via type literals) | array, struct, pointer, function, interface, slice, map, channel |
|
||||
|
||||
**Variables**
|
||||
|
||||
There are mainly 3 data types ie bool, Numeric (int and float32) and string.
|
||||
|
||||
There are 2 ways to declare a variable
|
||||
|
||||
1. with var keyword
|
||||
`var variablename type = value`(with initial value) or `var variablename type`(with no initial value)
|
||||
2. with `:=` sign
|
||||
`variablename := value ` . data type is assigned with initial value type so there is no way to declare it without initial value. Also this method can be only used inside a function
|
||||
|
||||
eg
|
||||
```go
|
||||
package main
|
||||
import ("fmt")
|
||||
|
||||
func main() {
|
||||
var student1 string = "John" //type is string
|
||||
var student2 = "Jane" //type is inferred
|
||||
x := 2 //type is inferred
|
||||
|
||||
fmt.Println(student1)
|
||||
fmt.Println(student2)
|
||||
fmt.Println(x)
|
||||
}
|
||||
```
|
||||
|
||||
for multiple values
|
||||
```go
|
||||
var a, b, c, d int = 1, 3, 5, 7
|
||||
```
|
||||
or
|
||||
```go
|
||||
var (
|
||||
a int
|
||||
b int = 1
|
||||
c string = "hello"
|
||||
)
|
||||
```
|
||||
|
||||
Similarly there are constants whose value cant be changed and is read-only
|
||||
it dont have that `:=` thing and can be even defined without type
|
||||
|
||||
```go
|
||||
const (
|
||||
A int = 1
|
||||
B = 3.14
|
||||
C = "Hi!"
|
||||
)
|
||||
```
|
||||
|
||||
|
||||
Output functions
|
||||
|
||||
It has `Print`, `Println` and `Printf`
|
||||
```go
|
||||
func main() {
|
||||
var i string = "Hello"
|
||||
fmt.Printf("i has value: %v and type: %T\n", i, i)
|
||||
}
|
||||
```
|
||||
%v and %T are formatting verbs
|
||||
```txt
|
||||
%v Prints the value in the default format
|
||||
%#v Prints the value in Go-syntax format
|
||||
%T Prints the type of the value
|
||||
%% Prints the % sign
|
||||
```
|
||||
|
||||
```go
|
||||
package main
|
||||
import ("fmt")
|
||||
|
||||
func main() {
|
||||
var i = 15.5
|
||||
var txt = "Hello World!"
|
||||
|
||||
fmt.Printf("%v\n", i)
|
||||
fmt.Printf("%#v\n", i)
|
||||
fmt.Printf("%v%%\n", i)
|
||||
fmt.Printf("%T\n", i)
|
||||
|
||||
fmt.Printf("%v\n", txt)
|
||||
fmt.Printf("%#v\n", txt)
|
||||
fmt.Printf("%T\n", txt)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
**Data types**
|
||||
|
||||
1. Integers
|
||||
`int`, `uint` for signed and unsigned integers . Also `int8`, `int16`, ..
|
||||
2. Float
|
||||
```go
|
||||
func main() {
|
||||
var x float64 = 1.7e+308
|
||||
fmt.Printf("Type: %T, value: %v", x, x)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### Arrays
|
||||
|
||||
Syntax
|
||||
```go
|
||||
var array_name = [length]datatype{values} // here length is defined
|
||||
|
||||
// or
|
||||
|
||||
var array_name = [...]datatype{values} // here length is inferred
|
||||
|
||||
// or
|
||||
|
||||
array_name := [length]datatype{values} // here length is defined
|
||||
|
||||
// or
|
||||
|
||||
array_name := [...]datatype{values} // here length is inferred
|
||||
|
||||
```
|
||||
|
||||
eg
|
||||
```go
|
||||
func main() {
|
||||
var arr1 = [3]int{1,2,3}
|
||||
arr2 := [...]int{4,5,6,7,8}
|
||||
// or
|
||||
// declaring a array with no initialization
|
||||
var a [5]int
|
||||
|
||||
fmt.Println(arr1)
|
||||
fmt.Println(arr2)
|
||||
}
|
||||
```
|
||||
|
||||
in case of integer array, if all the elements are not initialized then those remaining ones will be filled with 0.
|
||||
|
||||
To initialize specific elements
|
||||
```go
|
||||
func main() {
|
||||
arr1 := [5]int{1:10,2:40}
|
||||
|
||||
fmt.Println(arr1)
|
||||
|
||||
// to get length of array
|
||||
fmt.Println(len(arr1))
|
||||
}
|
||||
```
|
||||
|
||||
Output
|
||||
`[0 10 40 0 0] `
|
||||
|
||||
|
||||
and to find element position in array
|
||||
`index := slices.Index(myArray[:], target)`
|
||||
and for array of structs
|
||||
```go
|
||||
index := slices.IndexFunc(users[:], func(u User) bool {
|
||||
return u.ID == targetID
|
||||
})
|
||||
```
|
||||
|
||||
**Slices**
|
||||
|
||||
Slices are like arrays and unlike arrays its size can grow or shrink. It has length and capacity thing.
|
||||
|
||||
Syntax
|
||||
```go
|
||||
slice_name := []datatype{values}
|
||||
|
||||
and
|
||||
|
||||
slice_name := make([]type, length, capacity)
|
||||
|
||||
```
|
||||
|
||||
example
|
||||
```go
|
||||
func main() {
|
||||
myslice1 := []int{}
|
||||
fmt.Println(len(myslice1))
|
||||
fmt.Println(cap(myslice1))
|
||||
fmt.Println(myslice1)
|
||||
|
||||
myslice2 := []string{"Go", "Slices", "Are", "Powerful"}
|
||||
fmt.Println(len(myslice2))
|
||||
fmt.Println(cap(myslice2))
|
||||
fmt.Println(myslice2)
|
||||
|
||||
myslice3 := make([]int, 5, 10)
|
||||
}
|
||||
```
|
||||
|
||||
to change or access elements it is same as arrays. To append elemnts use append function
|
||||
`slice_name = append(slice_name, element1, element2, ...)` or
|
||||
`slice3 = append(slice1, slice2...)`
|
||||
|
||||
|
||||
For changing the length of array
|
||||
```go
|
||||
|
||||
func main() {
|
||||
arr1 := [6]int{9, 10, 11, 12, 13, 14} // An array
|
||||
myslice1 := arr1[1:5] // Slice array
|
||||
fmt.Printf("myslice1 = %v\n", myslice1)
|
||||
fmt.Printf("length = %d\n", len(myslice1))
|
||||
fmt.Printf("capacity = %d\n", cap(myslice1))
|
||||
|
||||
myslice1 = arr1[1:3] // Change length by re-slicing the array
|
||||
fmt.Printf("myslice1 = %v\n", myslice1)
|
||||
fmt.Printf("length = %d\n", len(myslice1))
|
||||
fmt.Printf("capacity = %d\n", cap(myslice1))
|
||||
|
||||
myslice1 = append(myslice1, 20, 21, 22, 23) // Change length by appending items
|
||||
fmt.Printf("myslice1 = %v\n", myslice1)
|
||||
fmt.Printf("length = %d\n", len(myslice1))
|
||||
fmt.Printf("capacity = %d\n", cap(myslice1))
|
||||
|
||||
|
||||
neededNumbers := arr3[:len(arr3)-4]
|
||||
numberCopy := make([]int, len(neededNumbers))
|
||||
copy(numberCopy, neededNumbers)
|
||||
|
||||
// or
|
||||
// neededNumbers... is like ...arr in js
|
||||
numberCopy = append([]int(nil), neededNumbers...)
|
||||
|
||||
|
||||
|
||||
fmt.Printf("numberCopy = %v\n", numberCopy)
|
||||
fmt.Printf("length = %d\n", len(numberCopy))
|
||||
fmt.Printf("capacity = %d\n", cap(numberCopy))
|
||||
fmt.Println("for neededNumbers:")
|
||||
fmt.Printf("capacity = %d\n", cap(neededNumbers))
|
||||
}
|
||||
```
|
||||
|
||||
Capacity will increase too automatically
|
||||
|
||||
|
||||
Memory Efficiency
|
||||
When copying elements from array, by default go will load all elements to memory so in order to copy few elements from large array it is better to use copy function.
|
||||
|
||||
|
||||
|
||||
**runes**
|
||||
character array of string but containing ascii code instead of characters
|
||||
```go
|
||||
import "unicode/utf8"
|
||||
|
||||
str:= "AB"
|
||||
runes:= []rune(str) // [65 66]
|
||||
|
||||
buf := make([]byte, utf8.RuneLen(runes[0]))
|
||||
utf8.EncodeRune(buf, runes[0]) // [65]
|
||||
|
||||
fmt.Println("string form: ", string(runes)) // AB
|
||||
|
||||
byteSlice := []byte(string(runes)) // [65 66]
|
||||
as character array
|
||||
fmt.Printf("%c\n", runes) // [A B]
|
||||
|
||||
|
||||
// to string slice
|
||||
sli := strings.Split(str, "") // [A B] -> not rune slice but string slice
|
||||
|
||||
slistr := strings.Join(sli, "") // AB
|
||||
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
byteslice is of utf8 so takes mostly text but rune slice covers much as its int32
|
||||
36
joplin notion extension/Web Development/Go/Initial.md
Normal file
36
joplin notion extension/Web Development/Go/Initial.md
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
Initial
|
||||
|
||||
Install go compiler.
|
||||
|
||||
Sample program
|
||||
```go
|
||||
|
||||
// file name : main.go
|
||||
package main
|
||||
import ("fmt")
|
||||
|
||||
func main() {
|
||||
fmt.Println("Hello World!")
|
||||
}
|
||||
```
|
||||
then run `go run main.go` or `go build -o main main.go && ./main`.
|
||||
for partilcular platform
|
||||
`GOOS=linux GOARCH=arm64 go build -o myapp-linux-arm64 . `
|
||||
and equivalent of `npm i`
|
||||
to install all packages
|
||||
`go get .` or `go mod tidy`
|
||||
to install specific package
|
||||
`go get github.com/spf13/cobra@latest`
|
||||
to remove go package
|
||||
simply remove import statements and then run `go mod tidy`
|
||||
|
||||
for initiating like `npm init -y`
|
||||
use `go mod init <module_name>`
|
||||
|
||||
|
||||
Program explanation
|
||||
1. in go every program is part of package that's why here is ths package main
|
||||
2. fmt package is imported
|
||||
3. main function
|
||||
4. fmt.Println is used to print text
|
||||
5. Comments are like in C ie `//` for single line and `/* */` for multi line
|
||||
4
joplin notion extension/Web Development/Go/Resources.md
Normal file
4
joplin notion extension/Web Development/Go/Resources.md
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
Resources
|
||||
|
||||
https://github.com/mauricioabreu/golings
|
||||
https://go.dev/tour/basics/1
|
||||
75
joplin notion extension/Web Development/Go/databases.md
Normal file
75
joplin notion extension/Web Development/Go/databases.md
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
databases
|
||||
|
||||
sqlite
|
||||
https://www.sqlitetutorial.net/sqlite-go/connect/
|
||||
|
||||
connecting
|
||||
|
||||
```go
|
||||
|
||||
func NewDB() *sql.DB {
|
||||
// err := errors.New("some error")
|
||||
|
||||
db, err := sql.Open("sqlite", "./main.db")
|
||||
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return nil
|
||||
}
|
||||
fmt.Println("Connected to the SQLite database successfully.")
|
||||
|
||||
|
||||
fmt.Println("Table countries was created successfully.")
|
||||
|
||||
return db
|
||||
}
|
||||
```
|
||||
|
||||
creating table
|
||||
```go
|
||||
func CreateTable(db *sql.DB) (sql.Result, error) {
|
||||
|
||||
sql := fmt.Sprintf(`CREATE TABLE IF NOT EXISTS %v(
|
||||
id TEXT PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
price REAL NOT NULL,
|
||||
file TEXT
|
||||
);`, TABLE_NAME)
|
||||
|
||||
return db.Exec(sql)
|
||||
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
findall
|
||||
|
||||
```go
|
||||
func FindAll(db *sql.DB) ([]types.Book, error) {
|
||||
|
||||
sql := fmt.Sprintf(`select * from %v`, TABLE_NAME)
|
||||
|
||||
rows, err := db.Query(sql)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var books []types.Book
|
||||
for rows.Next() {
|
||||
b := &types.Book{}
|
||||
err := rows.Scan(&b.Id, &b.Name, &b.Price, &b.Filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
books = append(books, *b)
|
||||
}
|
||||
|
||||
fmt.Println("finall: ", books)
|
||||
|
||||
return books, nil
|
||||
}
|
||||
```
|
||||
|
||||
we cant just use sql.Rows directly as it is stream so using Next() we read it row by row
|
||||
3
joplin notion extension/Web Development/Go/discordgo.md
Normal file
3
joplin notion extension/Web Development/Go/discordgo.md
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
discordgo
|
||||
https://github.com/bwmarrin/discordgo
|
||||
[discordgo-master.zip](../../../_resources/discordgo-master.zip)
|
||||
50
joplin notion extension/Web Development/Go/extras.md
Normal file
50
joplin notion extension/Web Development/Go/extras.md
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
extras
|
||||
|
||||
- to get type of variable
|
||||
`fmt.Println(reflect.TypeOf(student))`
|
||||
|
||||
- for signals
|
||||
`signal.Notify(sc, syscall.SIGINT, syscall.SIGTERM, os.Interrupt)`
|
||||
- sc — a chan os.Signal (must be buffered, e.g. make(chan os.Signal, 1)) that will receive the signal values.
|
||||
- syscall.SIGINT — interrupt from the keyboard (Ctrl+C).
|
||||
- syscall.SIGTERM — polite termination request (e.g. kill <pid> or what Kubernetes sends on pod shutdown).
|
||||
- os.Interrupt — a platform-agnostic alias; on Unix it's the same as syscall.SIGINT, on Windows it also covers Ctrl+Break.
|
||||
|
||||
|
||||
for deeply mested objects printing in console
|
||||
|
||||
```go
|
||||
data, _ := json.MarshalIndent(m, "", " ")
|
||||
fmt.Printf("detected: %v\n", string(data))
|
||||
```
|
||||
|
||||
|
||||
|
||||
go equivalent to `fs.mkdirSync(dirPath,{recursive: true}`
|
||||
|
||||
this will create directories recurselovely and wont throw error if it exist
|
||||
```go
|
||||
err := os.MkdirAll(dirPath, 0755)
|
||||
```
|
||||
|
||||
creating a build for all platfoms
|
||||
|
||||
script
|
||||
```sh
|
||||
#!/bin/bash
|
||||
# Iterate through all supported GOOS/GOARCH combinations
|
||||
go tool dist list | while read platform; do
|
||||
# Split platform into OS and ARCH
|
||||
GOOS=${platform%/*}
|
||||
GOARCH=${platform#*/}
|
||||
|
||||
# Define output filename
|
||||
output_name="myapp-${GOOS}-${GOARCH}"
|
||||
if [ "$GOOS" = "windows" ]; then
|
||||
output_name+=".exe"
|
||||
fi
|
||||
|
||||
# Build the binary
|
||||
env GOOS=$GOOS GOARCH=$GOARCH go build -o "$output_name" .
|
||||
done
|
||||
```
|
||||
21
joplin notion extension/Web Development/Go/regex.md
Normal file
21
joplin notion extension/Web Development/Go/regex.md
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
regex
|
||||
https://gobyexample.com/regular-expressions
|
||||

|
||||
|
||||
for url
|
||||
```go
|
||||
func DoesContainURL(str string) (bool, error) {
|
||||
// regex := `/^https?:\/\/(?:www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b(?:[-a-zA-Z0-9()@:%_\+.~#?&\/=]*)$/`
|
||||
regex := `https?://[^\s]+`
|
||||
|
||||
res, err := regexp.MatchString(regex, str)
|
||||
|
||||
fmt.Println("does: ", res)
|
||||
|
||||
return res, err
|
||||
}
|
||||
|
||||
DoesContainURL("sd http://yourrt.com/122 sads") // true
|
||||
|
||||
|
||||
```
|
||||
234
joplin notion extension/Web Development/Go/routing.md
Normal file
234
joplin notion extension/Web Development/Go/routing.md
Normal file
|
|
@ -0,0 +1,234 @@
|
|||
routing
|
||||
|
||||
**from llm**
|
||||
|
||||
Sure! Let's create a simple REST API in Go (Golang) and I'll explain everything step by step. By the end of this, you'll have a basic understanding of how to create and run a Go REST API.
|
||||
|
||||
---
|
||||
|
||||
### What is a REST API?
|
||||
A REST API (Representational State Transfer Application Programming Interface) is a way for two systems to communicate over HTTP. It uses standard HTTP methods like `GET`, `POST`, `PUT`, and `DELETE` to perform operations on resources (like data).
|
||||
|
||||
---
|
||||
|
||||
### Step 1: Install Go
|
||||
Before we start, make sure you have Go installed on your machine. You can download it from the official website: [https://golang.org/dl/](https://golang.org/dl/).
|
||||
|
||||
To verify the installation, run:
|
||||
```bash
|
||||
go version
|
||||
```
|
||||
You should see the installed Go version.
|
||||
|
||||
---
|
||||
|
||||
### Step 2: Create a Go Project
|
||||
1. Create a new directory for your project:
|
||||
```bash
|
||||
mkdir go-rest-api
|
||||
cd go-rest-api
|
||||
```
|
||||
|
||||
2. Initialize a Go module:
|
||||
```bash
|
||||
go mod init go-rest-api
|
||||
```
|
||||
This creates a `go.mod` file, which manages dependencies.
|
||||
|
||||
---
|
||||
|
||||
### Step 3: Write the REST API Code
|
||||
Create a file named `main.go` in your project directory and add the following code:
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
// Item represents a simple data structure
|
||||
type Item struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
// In-memory "database" to store items
|
||||
var items []Item
|
||||
|
||||
// Get all items
|
||||
func getItems(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(items)
|
||||
}
|
||||
|
||||
// Get a single item by ID
|
||||
func getItem(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
params := mux.Vars(r) // Get route parameters
|
||||
id, _ := strconv.Atoi(params["id"])
|
||||
|
||||
// Find the item with the matching ID
|
||||
for _, item := range items {
|
||||
if item.ID == id {
|
||||
json.NewEncoder(w).Encode(item)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// If not found, return a 404
|
||||
http.NotFound(w, r)
|
||||
}
|
||||
|
||||
// Create a new item
|
||||
func createItem(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
var item Item
|
||||
_ = json.NewDecoder(r.Body).Decode(&item) // Decode the request body into the item
|
||||
|
||||
// Assign a new ID and add to the list
|
||||
item.ID = len(items) + 1
|
||||
items = append(items, item)
|
||||
|
||||
json.NewEncoder(w).Encode(item)
|
||||
}
|
||||
|
||||
// Update an existing item
|
||||
func updateItem(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
params := mux.Vars(r)
|
||||
id, _ := strconv.Atoi(params["id"])
|
||||
|
||||
// Find the item and update it
|
||||
for index, item := range items {
|
||||
if item.ID == id {
|
||||
var updatedItem Item
|
||||
_ = json.NewDecoder(r.Body).Decode(&updatedItem)
|
||||
updatedItem.ID = id
|
||||
items[index] = updatedItem
|
||||
json.NewEncoder(w).Encode(updatedItem)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// If not found, return a 404
|
||||
http.NotFound(w, r)
|
||||
}
|
||||
|
||||
// Delete an item
|
||||
func deleteItem(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
params := mux.Vars(r)
|
||||
id, _ := strconv.Atoi(params["id"])
|
||||
|
||||
// Find the item and remove it
|
||||
for index, item := range items {
|
||||
if item.ID == id {
|
||||
items = append(items[:index], items[index+1:]...)
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// If not found, return a 404
|
||||
http.NotFound(w, r)
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Initialize the router
|
||||
router := mux.NewRouter()
|
||||
|
||||
// Add some initial data
|
||||
items = append(items, Item{ID: 1, Name: "Item 1"})
|
||||
items = append(items, Item{ID: 2, Name: "Item 2"})
|
||||
|
||||
// Define routes
|
||||
router.HandleFunc("/items", getItems).Methods("GET")
|
||||
router.HandleFunc("/items/{id}", getItem).Methods("GET")
|
||||
router.HandleFunc("/items", createItem).Methods("POST")
|
||||
router.HandleFunc("/items/{id}", updateItem).Methods("PUT")
|
||||
router.HandleFunc("/items/{id}", deleteItem).Methods("DELETE")
|
||||
|
||||
// Start the server
|
||||
fmt.Println("Server is running on port 8080...")
|
||||
log.Fatal(http.ListenAndServe(":8080", router))
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Step 4: Install Dependencies
|
||||
The code uses the `gorilla/mux` package for routing. Install it by running:
|
||||
```bash
|
||||
go get -u github.com/gorilla/mux
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Step 5: Run the API
|
||||
To run the API, use the following command:
|
||||
```bash
|
||||
go run main.go
|
||||
```
|
||||
|
||||
The server will start on `http://localhost:8080`.
|
||||
|
||||
---
|
||||
|
||||
### Step 6: Test the API
|
||||
You can use tools like [Postman](https://www.postman.com/) or `curl` to test the API.
|
||||
|
||||
#### Endpoints:
|
||||
1. **GET** `/items` - Get all items.
|
||||
2. **GET** `/items/{id}` - Get a single item by ID.
|
||||
3. **POST** `/items` - Create a new item.
|
||||
4. **PUT** `/items/{id}` - Update an existing item.
|
||||
5. **DELETE** `/items/{id}` - Delete an item.
|
||||
|
||||
#### Example Requests:
|
||||
- **Get all items:**
|
||||
```bash
|
||||
curl http://localhost:8080/items
|
||||
```
|
||||
|
||||
- **Get a single item:**
|
||||
```bash
|
||||
curl http://localhost:8080/items/1
|
||||
```
|
||||
|
||||
- **Create a new item:**
|
||||
```bash
|
||||
curl -X POST -H "Content-Type: application/json" -d '{"name": "New Item"}' http://localhost:8080/items
|
||||
```
|
||||
|
||||
- **Update an item:**
|
||||
```bash
|
||||
curl -X PUT -H "Content-Type: application/json" -d '{"name": "Updated Item"}' http://localhost:8080/items/1
|
||||
```
|
||||
|
||||
- **Delete an item:**
|
||||
```bash
|
||||
curl -X DELETE http://localhost:8080/items/1
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Explanation of the Code
|
||||
1. **`Item` Struct**: Represents a simple data structure with `ID` and `Name` fields.
|
||||
2. **`items` Slice**: Acts as an in-memory database to store items.
|
||||
3. **Routing**: The `gorilla/mux` package is used to define routes and handle HTTP methods.
|
||||
4. **Handlers**: Functions like `getItems`, `getItem`, `createItem`, `updateItem`, and `deleteItem` handle the logic for each endpoint.
|
||||
5. **JSON Encoding/Decoding**: The `encoding/json` package is used to convert Go structs to JSON and vice versa.
|
||||
|
||||
---
|
||||
|
||||
### Step 7: Learn More
|
||||
- Go Documentation: [https://golang.org/doc/](https://golang.org/doc/)
|
||||
- Gorilla Mux Documentation: [https://github.com/gorilla/mux](https://github.com/gorilla/mux)
|
||||
|
||||
Let me know if you have any questions! 😊
|
||||
176
joplin notion extension/Web Development/Go/snippets.md
Normal file
176
joplin notion extension/Web Development/Go/snippets.md
Normal file
|
|
@ -0,0 +1,176 @@
|
|||
snippets
|
||||
|
||||
js to go mappings
|
||||
[js-to-go.html](../../../_resources/js-to-go.html)
|
||||
[js-to-go_1.html](../../../_resources/js-to-go_1.html)
|
||||
|
||||

|
||||
|
||||
tracking time
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
func myExpensiveFunction() {
|
||||
// 1. Tracks starting time and defers the calculation
|
||||
defer func(start time.Time) {
|
||||
fmt.Printf("Function took: %v\n", time.Since(start))
|
||||
}(time.Now())
|
||||
|
||||
// 2. Your actual function logic here
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
}
|
||||
|
||||
func main() {
|
||||
myExpensiveFunction()
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
for printing tabular data
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"text/tabwriter"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Initialize tabwriter: output, minwidth, tabwidth, padding, padchar, flags
|
||||
w := tabwriter.NewWriter(os.Stdout, 1, 1, 3, ' ', 0)
|
||||
|
||||
// Print the header row (terminate columns with \t and rows with \n)
|
||||
fmt.Fprintln(w, "ID\tNAME\tROLE\tSTATUS\t")
|
||||
|
||||
// Print data rows
|
||||
fmt.Fprintln(w, "1\tAlice Vance\tDeveloper\tActive\t")
|
||||
fmt.Fprintln(w, "2\tBob Miller\tManager\tAway\t")
|
||||
fmt.Fprintln(w, "105\tCharlie\tDesigner\tOffline\t")
|
||||
|
||||
// Flush to format and output everything to the console
|
||||
w.Flush()
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
for env file parsing
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"github.com/joho/godotenv"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Loads .env file into os.Environ()
|
||||
err := godotenv.Load()
|
||||
if err != nil {
|
||||
log.Fatal("Error loading .env file")
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
or without external library
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func loadEnvFile(path string) error {
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
scanner := bufio.NewScanner(f)
|
||||
for scanner.Scan() {
|
||||
line := strings.TrimSpace(scanner.Text())
|
||||
|
||||
// skip empty lines and comments
|
||||
if line == "" || strings.HasPrefix(line, "#") {
|
||||
continue
|
||||
}
|
||||
|
||||
// strip optional "export " prefix
|
||||
line = strings.TrimPrefix(line, "export ")
|
||||
|
||||
// for inline comments
|
||||
if strings.HasPrefix(line, `"`) || strings.HasPrefix(line, `'`) {
|
||||
// quoted — keep everything between the quotes
|
||||
line = strings.Trim(line, `"'`)
|
||||
} else {
|
||||
// unquoted — cut at first " #" (space + hash)
|
||||
if idx := strings.Index(line, " #"); idx != -1 {
|
||||
line = strings.TrimSpace(line[:idx])
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
key, value, found := strings.Cut(line, "=")
|
||||
if !found {
|
||||
continue
|
||||
}
|
||||
|
||||
key = strings.TrimSpace(key)
|
||||
value = strings.TrimSpace(value)
|
||||
|
||||
// strip surrounding quotes
|
||||
value = strings.Trim(value, `"'`)
|
||||
|
||||
os.Setenv(key, value)
|
||||
}
|
||||
return scanner.Err()
|
||||
}
|
||||
|
||||
func main() {
|
||||
if err := loadEnvFile(".env"); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
fmt.Println(os.Getenv("DB_HOST"))
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
for timestamps
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
unixTimestamp := int64(1615460256)
|
||||
t := time.Unix(unixTimestamp, 0)
|
||||
isoString := t.Format(time.RFC3339)
|
||||
// or for readibility
|
||||
// timeISOString := time.Time.Local(t).String()
|
||||
// or for gmt
|
||||
// timeISOString := time.Time.UTC(t).Format(http.TimeFormat)
|
||||
fmt.Println(isoString) // Output: 2021-03-11T06:17:36Z
|
||||
}
|
||||
```
|
||||
|
||||
for milli sec one
|
||||
|
||||
```go
|
||||
unixMillis := int64(1615460256000)
|
||||
t := time.Unix(unixMillis/1000, (unixMillis%1000)*int64(time.Millisecond))
|
||||
fmt.Println(t.Format(time.RFC3339))
|
||||
```
|
||||
|
||||
Loading…
Reference in a new issue