diff --git a/foomo/docs/backend/go-by-example/channels.mdx b/foomo/docs/backend/go-by-example/channels.mdx new file mode 100644 index 0000000..e69de29 diff --git a/foomo/docs/backend/go-by-example/cli-applications.mdx b/foomo/docs/backend/go-by-example/cli-applications.mdx new file mode 100644 index 0000000..e69de29 diff --git a/foomo/docs/backend/go-by-example/context.mdx b/foomo/docs/backend/go-by-example/context.mdx new file mode 100644 index 0000000..92f8cfd --- /dev/null +++ b/foomo/docs/backend/go-by-example/context.mdx @@ -0,0 +1 @@ +https://gobyexample.com/context \ No newline at end of file diff --git a/foomo/docs/backend/go-by-example/defer.mdx b/foomo/docs/backend/go-by-example/defer.mdx new file mode 100644 index 0000000..de8658c --- /dev/null +++ b/foomo/docs/backend/go-by-example/defer.mdx @@ -0,0 +1,71 @@ +--- +title: Defer +sidebar_position: 1 +tags: + - Go Basics +--- +# Defer + +In a normal Go application, control flows from the top to the bottom of any function that we call (this is if you don't use branching or looping). +Through introducing ```defer``` we can execute the statement passed to it at the end of the function just before it returns. To demonstrate: +```go +package main + +import ( + "fmt" +) + +func main() { + fmt.Println("first") + fmt.Println("second") + fmt.Println("third") +} +``` +If you copy the above code and execute it it will print 'first', 'second' and then 'third'. Now if we introduce ```defer``` to this function we see the order in which our statements are printed change. + +```go +func main() { + fmt.Println("first") + defer fmt.Println("second") + fmt.Println("third") +} +``` +Executing this function will print: 'first', 'third' and then 'second'. This is because the statement that follows after the ```defer``` keyword is executed at the end of function we are calling, just before it returns. +When it goes through this function if will print 'first', then it will recognise it has a defer function to call, it will print 'third' and then when it exits the function, it will check if there are any defer functions to call and if so it will call them. +Which in our case is the print function that prints 'second'. +What would happen if we add the defer keyword before each of our prints? +```go +func main() { + defer fmt.Println("first") + defer fmt.Println("second") + defer fmt.Println("third") +} +``` +This results into 'third' being printed first, followed by 'second' and then 'first'. This is because the defer keyword executes in last-in-first-out (LIFO) order. +This makes sense because defer is usually used to close out resources, and it is logical to close these in the opposite order of which they are opened because one resource might be dependend on another one. + +It's good practice to use defer to close a response body right after you have opened it. In this way you make sure all resources that have been opened have been closed and in this way it can prevent some bugs. +What you will see often is something like this: + +```go +func main() { + resp, err := http.Get("http://www.foomo.org") + if err != nil { + log.Fatal(err) + } + defer resp.Body.Close() +} +``` +You open a resource, check if there is an error and after it use defer to close it before the function returns. + +Another thing to keep in mind with defer is that it will execute with the value given to it at the time. To demonstrate: +```go +func main() { + myVar := "hello" + defer fmt.Println(myVar) + myVar = "goodbye" +} +``` +What do you think this prints? You might think it will print 'goodbye' because that is the last value of the variable before the main function returns. +Surprisingly the value printed is 'hello', which is likely the result of a compiler optimization. + diff --git a/foomo/docs/backend/go-by-example/embed.mdx b/foomo/docs/backend/go-by-example/embed.mdx new file mode 100644 index 0000000..3363b65 --- /dev/null +++ b/foomo/docs/backend/go-by-example/embed.mdx @@ -0,0 +1 @@ +https://gobyexample.com/embed-directive \ No newline at end of file diff --git a/foomo/docs/backend/go-by-example/files.mdx b/foomo/docs/backend/go-by-example/files.mdx new file mode 100644 index 0000000..e69de29 diff --git a/foomo/docs/backend/go-by-example/goroutines.mdx b/foomo/docs/backend/go-by-example/goroutines.mdx new file mode 100644 index 0000000..e69de29 diff --git a/foomo/docs/backend/go-by-example/http.mdx b/foomo/docs/backend/go-by-example/http.mdx new file mode 100644 index 0000000..e69de29 diff --git a/foomo/docs/backend/go-by-example/interfaces.mdx b/foomo/docs/backend/go-by-example/interfaces.mdx new file mode 100644 index 0000000..4d94406 --- /dev/null +++ b/foomo/docs/backend/go-by-example/interfaces.mdx @@ -0,0 +1 @@ +todo \ No newline at end of file diff --git a/foomo/docs/backend/go-by-example/map-racing.md b/foomo/docs/backend/go-by-example/map-racing.md index c23638a..b539a33 100644 --- a/foomo/docs/backend/go-by-example/map-racing.md +++ b/foomo/docs/backend/go-by-example/map-racing.md @@ -1 +1,6 @@ -# map races \ No newline at end of file +--- +Title: Map Races +position: 7 +--- + +# Map Races diff --git a/foomo/docs/backend/go-by-example/mongodb.mdx b/foomo/docs/backend/go-by-example/mongodb.mdx new file mode 100644 index 0000000..15ef03d --- /dev/null +++ b/foomo/docs/backend/go-by-example/mongodb.mdx @@ -0,0 +1,103 @@ +--- +Title: MongoDB +position: 5 +tags: + - Go Basics +--- + +# MongoDB + +Make sure to use the official golang mongo driver: +> go.mongodb.org/mongo-driver/mongo + +This documentation is a simplified version of the tutorial on [MongoDB's website](https://www.mongodb.com/blog/post/mongodb-go-driver-tutorial) + +## Set client connections +```go +clientOptions := options.Client().ApplyURI() +``` + +## Connect with the database +```go +client, err := mongo.Connect(context.TODO(), clientOptions) +``` + +## Check connection +```go +err = client.Ping(context.TODO(), nil) +``` + +A collection is a grouping of MongoDB documents. Documents within a collection can have different fields. A collection is the equivalent of a table in a relational database system. A collection exists within a single database + + +source: Geeks for Geeks https://www.geeksforgeeks.org/mongodb-database-collection-and-document/ + +JSON documents in MongoDB are stored in a binary representation called BSON (Binary-encoded JSON). Unlike other databases that store JSON data as simple strings and numbers, the BSON encoding extends the JSON representation to include additional types such as int, long, date, floating point, and decimal128. This makes it much easier for applications to reliably process, sort, and compare data. The Go Driver has two families of types for representing BSON data: The D types and the Raw types. +The D family of types is used to concisely build BSON objects using native Go types: +* D: A BSON document. This type should be used in situations where order matters, such as MongoDB commands. +* M: An unordered map. It is the same as D, except it does not preserve order. +* A: A BSON array. +* E: A single element inside a D. + +You use filters to get the specific data you ask for. + +## CRUD Operations +### Insert one item +```go +insertResult, err := collection.InsertOne(context.TODO(), ) +``` + +### Insert Many +this takes a slice of objects +```go +my-slice := []interface{}{item1, item2} +insertManyResult, err := collection.InsertMany(context.TODO(), my-slice) +``` + +### Update a single document +Requires a filter document to match documents in the database and an update document to describe the update operation. +```go +filter := bson.D{{"name", “item1”}} +update := bson.D{ + {"$inc", bson.D{ // Increases var1 with 1 + {“var1”, 1}, + }}, +} +updateResult, err := collection.UpdateOne(context.TODO(), filter, update) +``` + +### Find a single document +Requires a filter document and a pointer to a value into which the result can be decoded, returns a single result which can be decoded into a value. +```go +var item_result Item // value into which the result can be decoded +err = collection.FindOne(context.TODO(), filter).Decode(&result) +``` + +### Find multiple documents +This method returns a Cursor. A Cursor provides a stream of documents through which you can iterate and decode one at a time. Once a Cursor has been exhausted, you should close the Cursor. +```go +findOptions := options.Find() +var results []*Item +cur, err := collection.Find(context.TODO(), bson.D{{}}, findOptions) +for cur.Next(context.TODO()) { + var elem Item + err := cur.Decode(&elem) + if err != nil { + log.Fatal(err) + } + results = append(results, &elem) +} +cur.Close(context.TODO()) +``` + +### Delete documents +You can choose to use collection.DeleteOne() or collection.DeleteMany(), both take a filter document to match the documents in the collection. +```go +deleteResult, err := collection.DeleteMany(context.TODO(), bson.D{{}}) +``` + +## Close connection +Best to keep connection open if you have to do multiple things. It does not make sense to open and close a connection if you have to query the database multiple times. +```go +err = client.Disconnect(context.TODO()) +``` \ No newline at end of file diff --git a/foomo/docs/backend/go-by-example/nil-maps.mdx b/foomo/docs/backend/go-by-example/nil-maps.mdx index 569198c..4e48347 100644 --- a/foomo/docs/backend/go-by-example/nil-maps.mdx +++ b/foomo/docs/backend/go-by-example/nil-maps.mdx @@ -1,6 +1,48 @@ +--- +title: Maps +sidebar_position: 3 +tags: + - Go Basics +--- + import { GoPlayground } from '../../../src/components/GoPlayground'; -# what you should now about nil maps +# Maps + +Maps are unordered key value pairs where each key is unique. +Unordered in that context means that the order can be different every time you iterate over its contents. +You can add, update, get, or delete keys and values. + +Map lookup operations will always return the value for the requested key and a boolean indicated whether the key was found. +In case the key was not found, the value will the default value for its data type (eg false for booleans, empty string for strings, nil for pointers etc) + +```go + musicMap := make(map[string]string) + + musicMap["Jimi"] = "Hendrix" // Add key and value pair + musicMap["Jimi"] = "Hendrix ❤️" // Update value + + v, found := musicMap["Jimi"] // Get a value for an existing key, will return found==true + v, found := musicMap["Jimmy"] // Get value for a non existing key: will return found==false + + delete(musicMap, "Jimi") // Deletes Jimi key value pair +``` + +## What you should now about nil maps + +Consider the following two maps: + +```go + var map1 map[string]int + map2 := make(map[string]int) +``` +What is the difference between these two? If you will add keys to one of them the program will panic while you can add keys +without a problem to the other. Map1 is a *nil map*, because it has not been initialized. Map2 is an empty map but because it is initialized +with the make statement you can add elements to this map later on in your program. Nil maps could for example be used for structs that have optional data. In that case +we don't want to allocate them every time, only when the data is present. +
+ +While you can not add elements to a nil map, read operations work just fine. Try it out yourself in the following example: +The function that panics will stop because it can no longer function so we don't see 'Is this printed?' printed. +The recover function makes it possible to obtain the error in case a panic occurred, and leaves the decision how to proceed to the programmer. +In this example, we decided to just log the error and continue to run. The function that panicked will stop execution at the panic, but the code that called it will continue to execute, +which is why we see 'End' being printed. \ No newline at end of file diff --git a/foomo/docs/backend/go-by-example/ranging.mdx b/foomo/docs/backend/go-by-example/ranging.mdx index eb189a1..2b372c2 100644 --- a/foomo/docs/backend/go-by-example/ranging.mdx +++ b/foomo/docs/backend/go-by-example/ranging.mdx @@ -1,9 +1,15 @@ +--- +title: Ranging and Looping +sidebar_position: 4 +tags: + - Go Basics +--- + import { GoPlayground } from '../../../src/components/GoPlayground'; -# ranging and looping +# Ranging and Looping - +/> \ No newline at end of file diff --git a/foomo/docs/backend/go-by-example/reflection.mdx b/foomo/docs/backend/go-by-example/reflection.mdx new file mode 100644 index 0000000..559b465 --- /dev/null +++ b/foomo/docs/backend/go-by-example/reflection.mdx @@ -0,0 +1,8 @@ +--- +Title: Reflection +position: 8 +--- + +# Reflection + +In go variables have a static type. \ No newline at end of file diff --git a/foomo/docs/backend/go-by-example/type-casting.mdx b/foomo/docs/backend/go-by-example/type-casting.mdx index e396364..a46d256 100644 --- a/foomo/docs/backend/go-by-example/type-casting.mdx +++ b/foomo/docs/backend/go-by-example/type-casting.mdx @@ -1,8 +1,15 @@ +--- +Title: Type Casting +position: 6 +tags: + - Go Intermediate +--- + import { GoPlayground } from '../../../src/components/GoPlayground'; -# type casting +# Type Casting diff --git a/foomo/docusaurus.config.js b/foomo/docusaurus.config.js index 7eae368..01b33f1 100644 --- a/foomo/docusaurus.config.js +++ b/foomo/docusaurus.config.js @@ -171,10 +171,9 @@ const config = { // algolia: { // contextualSearch: true, // } - // prism: { - // theme: lightCodeTheme, - // darkTheme: darkCodeTheme, - // }, + prism: { + additionalLanguages: ['go'], + }, }), }; diff --git a/foomo/static/img/mongodb.png b/foomo/static/img/mongodb.png new file mode 100644 index 0000000..637a993 Binary files /dev/null and b/foomo/static/img/mongodb.png differ