Skip to content

Commit

Permalink
Merge branch 'writing-improvement' of github.com:novalagung/dasarpemr…
Browse files Browse the repository at this point in the history
…ogramangolang into writing-improvement
  • Loading branch information
novalagung committed Apr 23, 2024
2 parents 0e25d59 + 359c323 commit 270beca
Show file tree
Hide file tree
Showing 40 changed files with 244 additions and 240 deletions.
6 changes: 3 additions & 3 deletions content/2-instalasi-golang.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ URL untuk mengunduh *installer* Go: https://golang.org/dl/. Silakan langsung und

## A.2.1. Instalasi Go *Stable*

#### Instalasi Go di Windows
#### Instalasi Go di Windows

1. Download terlebih dahulu *installer*-nya di [https://golang.org/dl/](https://golang.org/dl/). Pilih *installer* untuk sistem operasi Windows sesuai jenis bit yang digunakan.

Expand All @@ -26,7 +26,7 @@ URL untuk mengunduh *installer* Go: https://golang.org/dl/. Silakan langsung und

> Sering terjadi, command `go version` tidak bisa dijalankan meskipun instalasi sukses. Solusinya bisa dengan restart CMD (tutup CMD, kemudian buka lagi). Setelah itu coba jalankan ulang command di atas.

#### Instalasi Go di MacOS
#### Instalasi Go di MacOS

Cara termudah instalasi Go di MacOS adalah menggunakan [Homebrew](http://brew.sh/).

Expand Down Expand Up @@ -57,7 +57,7 @@ Cara termudah instalasi Go di MacOS adalah menggunakan [Homebrew](http://brew.sh

5. Jika output adalah sama dengan versi Go yang ter-*install*, menandakan proses instalasi berhasil.

#### Instalasi Go di Linux
#### Instalasi Go di Linux

1. Unduh arsip *installer* dari [https://golang.org/dl/](https://golang.org/dl/), pilih installer untuk Linux yang sesuai dengan jenis bit komputer anda. Proses download bisa dilakukan lewat CLI, menggunakan `wget` atau `curl`.

Expand Down
2 changes: 1 addition & 1 deletion content/A-buffered-channel.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ Pengiriman data indeks ke 0, 1, 2 dan 3 akan berjalan secara asynchronous, hal i

Karena pengiriman dan penerimaan data via buffered channel terjadi tidak selalu synchronous (tergantung jumlah buffer-nya), maka ada kemungkinan dimana eksekusi program selesai namun tidak semua data diterima via channel `messages`. Karena alasan ini pada bagian akhir ditambahkan statement `time.Sleep(1 * time.Second)` agar ada jeda 1 detik sebelum program selesai.

#### Fungsi `time.Sleep()`
#### Fungsi `time.Sleep()`

Fungsi ini digunakan untuk menambahkan delay sebelum statement berikutnya dieksekusi. Durasi delay ditentukan oleh parameter, misal `1 * time.Second` maka durasi delay adalah 1 detik.

Expand Down
6 changes: 3 additions & 3 deletions content/A-channel-range-close.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,11 @@ Setelah 20 data yang dikirim sukses diterima, channel `ch` di-non-aktifkan denga

![Penerapan for-range-close pada channel](images/A_channel_range_close_1_for_range_close.png)

---
## A.34.2. Penjelasan tambahan

Berikut adalah penjelasan tambahan mengenai channel.
Berikut merupakan penjelasan tambahan untuk beberapa hal dari kode yang sudah dipraktekan:

## A.34.1.1. Channel Direction
#### Channel Direction

Go mendesain API channel untuk mendukung level akses channel, apakah hanya sebagai penerima, pengirim, atau penerima sekaligus pengirim. Konsep ini disebut dengan **channel direction**.

Expand Down
8 changes: 4 additions & 4 deletions content/A-channel.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,11 +131,11 @@ Passing data bertipe channel lewat parameter sifatnya **pass by reference**, yan

![Parameter channel](images/A_channel_3_channel_param.png)

---
## A.32.3. Penjelasan tambahan

Berikut merupakan penjelasan tambahan untuk kode di atas.
Berikut merupakan penjelasan tambahan untuk beberapa hal dari kode yang sudah dipraktekan:

#### Iterasi Data Slice/Array Langsung Pada Saat Inisialisasi
#### Iterasi Data Slice/Array Langsung Pada Saat Inisialisasi

Data slice yang baru di inisialisasi bisa langsung di-iterasi, caranya mudah dengan menuliskannya langsung setelah keyword `range`.

Expand All @@ -145,7 +145,7 @@ for _, each := range []string{"wick", "hunt", "bourne"} {
}
```

#### Eksekusi Goroutine Pada IIFE
#### Eksekusi Goroutine Pada IIFE

Eksekusi goroutine tidak harus pada fungsi atau closure yang sudah terdefinisi. Sebuah IIFE juga bisa dijalankan sebagai goroutine baru. Caranya dengan langsung menambahkan keyword `go` pada waktu deklarasi-eksekusi IIFE-nya.

Expand Down
10 changes: 5 additions & 5 deletions content/A-concurrency-pipeline.md
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ Pada bagian ini kita akan re-write ulang program 2, isinya masih sama persis kal

Kenapa kita pecah, karena ketiga proses tersebut bisa dijalankan bersama secara konkuren, dalam artian misalnya ketika `file1` sudah selesai dibaca, perhitungan md5sum-nya bisa dijalankan secara bersama dengan pembacaan `file2`. Begitu juga untuk proses rename-nya, misalnya, proses rename `file24` bisa dijalnkan secara konkuren bersamaan dengan proses hitung md5sum `file22` dan bersamaan dengan proses baca `file28`.

#### Basis Kode Program
#### Basis Kode Program

Mungkin agar lebih terlihat perbandingannya nanti di akhir, kita siapkan file terpisah saja untuk program ini. Siapkan file baru bernama `3-find-md5-sum-of-file-then-rename-it-concurrently.go`.

Expand Down Expand Up @@ -291,7 +291,7 @@ type FileInfo struct {

Kurang lebih sama seperti sebelumnya, hanya saja ada beberapa packages lain yg di-import dan ada struct `FileInfo`. Struct ini digunakan sebagai metadata tiap file. Karena nantinya proses read file, md5sum, dan rename file akan dipecah menjadi 3 goroutine berbeda, maka perlu ada metadata untuk mempermudah tracking file, agar nanti ketika dapat md5 sum nya tidak salah simpan, dan ketika rename tidak salah file.

#### Pipeline 1: Baca File
#### Pipeline 1: Baca File

Siapkan fungsi main, lalu panggil fungsi `readFiles()`.

Expand Down Expand Up @@ -359,7 +359,7 @@ Mengenai channel `chanOut` sendiri, akan di-close ketika dipastikan **semua file

Ok lanjut, karena di sini ada channel yang digunakan sebagai media pengiriman data (`FileInfo`), maka juga harus ada penerima data channel-nya dong. Yups.

#### Pipeline 2: MD5 Hash Konten File
#### Pipeline 2: MD5 Hash Konten File

Tepat di bawah pipeline 1, tambahkan pemanggilan fungsi `getSum()` sebanyak 3x, bisa lebih banyak sih sebenarnya, bebas. Kemudian jadikan nilai balik pemanggilan fungsi tersebut sebagai variadic argument pemanggilan fungsi `mergeChanFileInfo()`.

Expand Down Expand Up @@ -447,7 +447,7 @@ Secara garis besar, pada fungsi ini terjadi beberapa proses:
* Channel `chanOut` ini dijadikan sebagai nilai balik fungsi.
* Di situ kita gunakan `sync.WaitGroup` untuk kontrol goroutine. Kita akan tunggu hingga semua channel input adalah closed, setelah itu barulah kita close channel `chanOut` ini.

#### Pipeline 3: Rename file
#### Pipeline 3: Rename file

Tambahkan statement pipeline ketiga, yaitu pemanggilan fungsi Fan-out `rename()`, lalu panggil fungsi Fan-in `mergeChanFileInfo()` untuk multiplex channel kembalian fungsi `rename()`.

Expand Down Expand Up @@ -493,7 +493,7 @@ Bisa dilihat di atas kita rename file asli yang informasi path-nya ada di `FileI

Setelah semua file berhasil di-rename, maka channel `chanOut` di-close.

#### Pipeline 4 / Output
#### Pipeline 4 / Output

Serangkaian proses yang sudah kita setup punya ketergantungan tinggi satu sama lain, dan eksekusinya harus berurutan meskipun *concurrently*. Ini secara langsung juga mempermudah kita dalam mengolah output hasil pipeline. Kita cukup fokus ke channel hasil Fan-in yang paling terakhir, yaitu channel `chanRename`.

Expand Down
16 changes: 8 additions & 8 deletions content/A-data-type-conversion.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Di beberapa chapter sebelum ini kita telah menerapkan beberapa cara konversi dat

Package `strconv` berisi banyak fungsi yang sangat membantu kita untuk melakukan konversi. Berikut merupakan beberapa fungsi yang dalam package tersebut.

#### Fungsi `strconv.Atoi()`
#### Fungsi `strconv.Atoi()`

Fungsi ini digunakan untuk konversi data dari tipe `string` ke `int`. `strconv.Atoi()` menghasilkan 2 buah nilai kembalian, yaitu hasil konversi dan `error` (jika konversi sukses, maka `error` berisi `nil`).

Expand All @@ -26,7 +26,7 @@ func main() {
}
```

#### Fungsi `strconv.Itoa()`
#### Fungsi `strconv.Itoa()`

Merupakan kebalikan dari `strconv.Atoi`, berguna untuk konversi `int` ke `string`.

Expand All @@ -37,7 +37,7 @@ var str = strconv.Itoa(num)
fmt.Println(str) // "124"
```

#### Fungsi `strconv.ParseInt()`
#### Fungsi `strconv.ParseInt()`

Digunakan untuk konversi `string` berbentuk numerik dengan basis tertentu ke tipe numerik non-desimal dengan lebar data bisa ditentukan.

Expand All @@ -63,7 +63,7 @@ if err == nil {
}
```

#### Fungsi `strconv.FormatInt()`
#### Fungsi `strconv.FormatInt()`

Berguna untuk konversi data numerik `int64` ke `string` dengan basis numerik bisa ditentukan sendiri.

Expand All @@ -74,7 +74,7 @@ var str = strconv.FormatInt(num, 8)
fmt.Println(str) // 30
```

#### Fungsi `strconv.ParseFloat()`
#### Fungsi `strconv.ParseFloat()`

Digunakan untuk konversi `string` ke numerik desimal dengan lebar data bisa ditentukan.

Expand All @@ -89,7 +89,7 @@ if err == nil {

Pada contoh di atas, string `"24.12"` dikonversi ke float dengan lebar tipe data `float32`. Hasil konversi `strconv.ParseFloat` adalah sesuai dengan standar [IEEE Standard for Floating-Point Arithmetic](https://en.wikipedia.org/wiki/IEEE_floating_point).

#### Fungsi `strconv.FormatFloat()`
#### Fungsi `strconv.FormatFloat()`

Berguna untuk konversi data bertipe `float64` ke `string` dengan format eksponen, lebar digit desimal, dan lebar tipe data bisa ditentukan.

Expand All @@ -113,7 +113,7 @@ Ada beberapa format eksponen yang bisa digunakan. Detailnya bisa dilihat di tabe
| `g` | Akan menggunakan format eksponen `e` untuk eksponen besar dan `f` untuk selainnya |
| `G` | Akan menggunakan format eksponen `E` untuk eksponen besar dan `f` untuk selainnya |

#### Fungsi `strconv.ParseBool()`
#### Fungsi `strconv.ParseBool()`

Digunakan untuk konversi `string` ke `bool`.

Expand All @@ -126,7 +126,7 @@ if err == nil {
}
```

#### Fungsi `strconv.FormatBool()`
#### Fungsi `strconv.FormatBool()`

Digunakan untuk konversi `bool` ke `string`.

Expand Down
8 changes: 4 additions & 4 deletions content/A-defer-exit.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ func main() {
}
```

Output:
Output program:

![Penerapan `defer`](images/A_defer_exit_1_defer.png)

Expand All @@ -45,7 +45,7 @@ func orderSomeFood(menu string) {
}
```

Output:
Output program:

![Penerapan `defer` dengan `return`](images/A_defer_exit_2_defer_return.png)

Expand All @@ -68,7 +68,7 @@ func main() {
}
```

Output:
Output program:

```
halo 1
Expand All @@ -95,7 +95,7 @@ func main() {
}
```

Output:
Output program:

```
halo 1
Expand Down
2 changes: 1 addition & 1 deletion content/A-error-panic-recover.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ func main() {
}
```

Output:
Output program:

![Handle panic menggunakan recover](images/A_error_panic_recover_4_recover.png)

Expand Down
26 changes: 13 additions & 13 deletions content/A-file.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# A.50. File

Ada beberapa cara yang bisa digunakan untuk operasi file di Go. Pada chapter ini kita akan mempelajari teknik yang paling dasar, yaitu dengan memanfaatkan `os.File`.
Pada chapter ini kita akan belajar beberapa teknik operasi file yang paling dasar.

## A.50.1. Membuat File Baru

Pembuatan file di Go sangatlah mudah, cukup dengan memanggil fungsi `os.Create()` lalu memasukkan path file yang ingin dibuat sebagai parameter. Jika ternyata file yang akan dibuat sudah ada, maka akan ditimpa. Bisa memanfaatkan `os.IsNotExist()` untuk mendeteksi apakah file sudah dibuat atau belum.
Pembuatan file di Go sangat mudah, dilakukan dengan memanfaatkan fungsi `os.Create()` disertai path file sebagai argument pemanggilan fungsi. Jika ternyata file yang akan dibuat sudah ada duluan, maka operasi `os.Create()` akan menimpa file yang sudah ada dengan file baru. Untuk menghindari penimpaan file, gunakan fungsi `os.IsNotExist()` untuk mendeteksi apakah file yang ingin dibuat sudah ada atau belum.

Berikut merupakan contoh pembuatan file.
Contoh program operasi pembuatan file:

```go
package main
Expand Down Expand Up @@ -43,17 +43,17 @@ func main() {
}
```

Fungsi `os.Stat()` mengembalikan 2 data, yaitu informasi tetang path yang dicari, dan error (jika ada). Masukkan error kembalian fungsi tersebut sebagai parameter fungsi `os.IsNotExist()`, untuk mendeteksi apakah file yang akan dibuat sudah ada. Jika belum ada, maka fungsi tersebut akan mengembalikan nilai `true`.
Fungsi `os.Stat()` mengembalikan 2 data, yaitu informasi tetang path yang dicari, dan error (jika ada). Masukkan error kembalian fungsi tersebut sebagai argument pemanggilan fungsi `os.IsNotExist()`, untuk mengetahui apakah file yang akan dibuat sudah ada. Jika rupanya file belum ada ada, maka fungsi tersebut akan mengembalikan nilai `true`.

Fungsi `os.Create()` digunakan untuk membuat file pada path tertentu. Fungsi ini mengembalikan objek `*os.File` dari file yang bersangkutan. File yang baru terbuat statusnya adalah otomatis **open**, maka dari itu perlu untuk di-**close** menggunakan method `file.Close()` setelah file tidak digunakan lagi.
Fungsi `os.Create()` ini mengembalikan objek bertipe `*os.File`. File yang baru dibuat, statusnya adalah otomatis **open**. Setelah operasi file selesai, file harus di-**close** menggunakan method `file.Close()`.

Membiarkan file terbuka ketika sudah tak lagi digunakan bukan hal yang baik, karena efeknya ke memory dan akses ke file itu sendiri, file akan di-lock sehingga tidak bisa digunakan oleh proses lain selama status file masih open atau belum di-close.
Membiarkan file terbuka ketika sudah tak lagi digunakan adalah tidak baik, karena ada efek ke memory dan akses ke file itu sendiri, file menjadi terkunci/locked, membuatnya tidak bisa diakses oleh proses lain selama status file statusnya masih **open** dan belum di-close.

![Membuat file baru](images/A_file_1_create.png)

## A.50.2. Mengedit Isi File

Untuk mengedit file, yang perlu dilakukan pertama adalah membuka file dengan level akses **write**. Setelah mendapatkan objek file-nya, gunakan method `WriteString()` untuk pengisian data. Terakhir panggil method `Sync()` untuk menyimpan perubahan.
Untuk mengedit file, yang pertama perlu dilakukan adalah membuka file dengan level akses **write**. Setelah mendapatkan objek file-nya, gunakan method `WriteString()` untuk penulisan data. Di akhir, panggil method `Sync()` untuk menyimpan perubahan.

```go
func writeFile() {
Expand All @@ -80,13 +80,13 @@ func main() {
}
```

Pada program di atas, file dibuka dengan level akses **read** dan **write** dengan kode permission **0664**. Setelah itu, beberapa string diisikan ke dalam file tersebut menggunakan `WriteString()`. Di akhir, semua perubahan terhadap file akan disimpan dengan dipanggilnya `Sync()`.
Pada program di atas, file dibuka dengan level akses **read** dan **write** dengan kode permission **0664**. Setelah itu, beberapa string diisikan ke dalam file tersebut menggunakan `WriteString()`. Di akhir, semua perubahan terhadap file menjadi tersimpan dengan adanya pemanggilan method `Sync()`.

![Mengedit file](images/A_file_2_write.png)

## A.50.3. Membaca Isi File

File yang ingin dibaca harus dibuka terlebih dahulu menggunakan fungsi `os.OpenFile()` dengan level akses minimal adalah **read**. Setelah itu, gunakan method `Read()` dengan parameter adalah variabel, yang di mana hasil proses baca akan disimpan ke variabel tersebut.
File yang ingin dibaca harus dibuka terlebih dahulu menggunakan fungsi `os.OpenFile()` dengan level akses minimal adalah **read**. Dari object file kembalian fungsi tersebut, gunakan method `Read()` dengan disertai argument berupa variabel yang akan menampung data hasil operasi baca.

```go
// tambahkan di bagian import package io
Expand Down Expand Up @@ -120,21 +120,21 @@ func main() {
}
```

Pada kode di atas `os.OpenFile()` digunakan untuk membuka file. Fungsi tersebut memiliki beberapa parameter.
Fungsi `os.OpenFile()` dalam pemanggilannya memerlukan beberapa argument parameter untuk di-isi:

1. Parameter pertama adalah path file yang akan dibuka.
2. Parameter kedua adalah level akses. `os.O_RDONLY` maksudnya adalah **read only**.
3. Parameter ketiga adalah permission file-nya.

Variabel `text` disiapkan bertipe slice `[]byte` dengan alokasi elemen 1024. Variabel tersebut bertugas menampung data hasil statement `file.Read()`. Proses pembacaan file akan dilakukan terus menerus, berurutan dari baris pertama hingga akhir.
Variabel `text` disiapkan bertipe slice `[]byte` dengan alokasi elemen `1024`. Variabel tersebut bertugas menampung data hasil statement `file.Read()`. Proses pembacaan file dilakukan terus menerus, berurutan dari baris pertama hingga akhir.

Error yang muncul ketika eksekusi `file.Read()` akan di-filter, ketika error tersebut adalah selain `io.EOF` maka proses baca file akan berlanjut. Error `io.EOF` sendiri menandakan bahwa file yang sedang dibaca adalah baris terakhir isi atau **end of file**.
Error yang muncul ketika eksekusi `file.Read()` akan di-filter, ketika error adalah selain `io.EOF` maka proses baca file akan berlanjut. Error `io.EOF` sendiri menandakan bahwa file yang sedang dibaca adalah baris terakhir isi atau **end of file**.

![Membaca isi file](images/A_file_3_read.png)

## A.50.4. Menghapus File

Cara menghapus file sangatlah mudah, cukup panggil fungsi `os.Remove()`, masukan path file yang ingin dihapus sebagai parameter.
Operasi menghapus file dilakukan via fungsi `os.Remove()`. Panggil fungsi tersebut, kemudian isi path dari file yang ingin dihapus sebagai argument fungsi.

```go
func deleteFile() {
Expand Down
Loading

0 comments on commit 270beca

Please sign in to comment.