Tutorial Golang: Belajar Bahasa Pemrograman Go untuk Pemula
Apa itu Pergi?
Go (juga dikenal sebagai Golang) adalah bahasa pemrograman sumber terbuka yang dikembangkan oleh Google. Bahasa ini merupakan bahasa kompilasi bertipe statis. Go mendukung pemrograman bersamaan, yaitu memungkinkan menjalankan beberapa proses secara bersamaan. Hal ini dicapai dengan menggunakan saluran, goroutine, dsb. Bahasa Go memiliki garbage collection yang mengelola memori dan memungkinkan eksekusi fungsi yang tertunda.
Kita akan mempelajari semua dasar-dasar Golang dalam Tutorial Belajar Bahasa Go ini.
Cara Mengunduh dan menginstal GO
Langkah 1) Pergi ke https://golang.org/dl/. Unduh biner untuk OS Anda.
Langkah 2) Double klik pada penginstal dan klik Jalankan.
Langkah 3) Klik Berikutnya
Langkah 4) Pilih folder instalasi dan klik Berikutnya.
Langkah 5) Klik Selesai setelah instalasi selesai.
Langkah 6) Setelah instalasi selesai Anda dapat memverifikasinya dengan membuka terminal dan mengetik
go version
Ini akan menampilkan versi go yang diinstal
Program Go Pertama Anda – Go Hello World!
Buat folder bernama studyGo. Dalam tutorial bahasa Go ini, kita akan membuat program go kita di dalam folder ini. File Go dibuat dengan ekstensi .Pergilah. Anda dapat menjalankan program Go menggunakan sintaksis
go run <filename>
Buat file bernama first.go dan tambahkan kode di bawah ini ke dalamnya dan simpan
package main import ("fmt") func main() { fmt.Println("Hello World! This is my first Go program\n") }
Arahkan ke folder ini di terminal Anda. Jalankan program menggunakan perintah
ayo lari dulu.pergi
Anda dapat melihat hasil pencetakannya
Hello World! This is my first Go program
Sekarang mari kita bahas program diatas.
paket utama – Setiap program Bahasa Go harus dimulai dengan nama paket. Go mengijinkan kita untuk menggunakan paket-paket di program go lain dan karenanya mendukung penggunaan kembali kode. Eksekusi program Go dimulai dengan kode di dalam paket bernama main.
import fmt – mengimpor paket fmt. Paket ini mengimplementasikan fungsi I/O.
func main() – Ini adalah fungsi tempat eksekusi program dimulai. Fungsi main harus selalu ditempatkan di paket utama. Di bawah main(), Anda dapat menulis kode di dalam {}.
fmt.Println – Ini akan mencetak teks di layar dengan fungsi Println dari fmt.
Catatan: Pada bagian di bawah tutorial Go ini, ketika Anda menyebutkan mengeksekusi/menjalankan kode, itu berarti menyimpan kode dalam file dengan ekstensi .go dan menjalankannya menggunakan sintaksis
go run <filename>
Jenis Data
Tipe(tipe data) mewakili tipe nilai yang disimpan dalam variabel, tipe nilai yang dikembalikan fungsi, dll.
Ada tiga tipe dasar dalam Bahasa Go
Tipe numerik – Mewakili nilai numerik yang mencakup nilai integer, floating point, dan kompleks. Berbagai jenis numerik adalah:
int8 – bilangan bulat bertanda 8 bit.
int16 – bilangan bulat bertanda 16 bit.
int32 – bilangan bulat bertanda 32 bit.
int64 – bilangan bulat bertanda 64 bit.
uint8 – 8 bit bilangan bulat tidak bertanda tangan.
uint16 – 16 bit bilangan bulat tidak bertanda tangan.
uint32 – 32 bit bilangan bulat tidak bertanda tangan.
uint64 – 64 bit bilangan bulat tidak bertanda tangan.
float32 – angka floating point 32 bit.
float64 – angka floating point 64 bit.
complex64 – memiliki float32 bagian nyata dan imajiner.
complex128 – memiliki float32 bagian nyata dan imajiner.
Jenis string – Mewakili serangkaian byte (karakter). Anda dapat melakukan berbagai operasi pada string seperti penggabungan string, mengekstrak substring, dll.
Tipe Boolean – Mewakili 2 nilai, benar atau salah.
Antarmuka Golang
Antarmuka Golang adalah kumpulan tanda tangan metode yang digunakan oleh suatu Tipe untuk mengimplementasikan perilaku objek. Tujuan utama antarmuka Golang adalah untuk menyediakan tanda tangan metode dengan nama, argumen, dan tipe kembalian. Terserah Tipe untuk mendeklarasikan dan mengimplementasikan metode ini. Antarmuka di Golang dapat dideklarasikan menggunakan kata kunci “antarmuka”.
Variabel
Variabel menunjuk ke lokasi memori yang menyimpan beberapa jenis nilai. Parameter tipe (dalam sintaks di bawah) mewakili tipe nilai yang dapat disimpan di lokasi memori.
Variabel dapat dideklarasikan menggunakan sintaks
var <variable_name> <type>
Setelah Anda mendeklarasikan variabel dari suatu tipe, Anda dapat menetapkan variabel tersebut ke nilai apa pun dari tipe tersebut.
Anda juga dapat memberikan nilai awal ke suatu variabel selama deklarasi itu sendiri menggunakan
var <variable_name> <type> = <value>
Jika Anda mendeklarasikan variabel dengan nilai awal, lalu simpulkan jenis variabel dari jenis nilai yang ditetapkan. Jadi Anda dapat menghilangkan tipe tersebut selama deklarasi menggunakan sintaks
var <variable_name> = <value>
Selain itu, Anda dapat mendeklarasikan banyak variabel dengan sintaksis
var <variable_name1>, <variable_name2> = <value1>, <value2>
Program di bawah dalam tutorial Go ini memiliki beberapa contoh deklarasi variabel Golang
package main import "fmt" func main() { //declaring a integer variable x var x int x=3 //assigning x the value 3 fmt.Println("x:", x) //prints 3 //declaring a integer variable y with value 20 in a single statement and prints it var y int=20 fmt.Println("y:", y) //declaring a variable z with value 50 and prints it //Here type int is not explicitly mentioned var z=50 fmt.Println("z:", z) //Multiple variables are assigned in single line- i with an integer and j with a string var i, j = 100,"hello" fmt.Println("i and j:", i,j) }
Outputnya akan menjadi
x: 3 y: 20 z: 50 i and j: 100 hello
Go Language juga menyediakan cara mudah untuk mendeklarasikan variabel yang mempunyai nilai dengan menghilangkan penggunaan kata kunci var
<variable_name> := <value>
Perhatikan bahwa Anda menggunakan := alih-alih =. Anda tidak dapat menggunakan := hanya untuk memberikan nilai pada variabel yang sudah dideklarasikan. := digunakan untuk mendeklarasikan dan menetapkan nilai.
Buat file bernama assign.go dengan kode berikut
package main import ("fmt") func main() { a := 20 fmt.Println(a) //gives error since a is already declared a := 30 fmt.Println(a) }
Jalankan go run task.go untuk melihat hasilnya
./assign.go:7:4: no new variables on left side of :=
Variabel yang dideklarasikan tanpa nilai awal akan bernilai 0 untuk tipe numerik, false untuk Boolean, dan string kosong untuk string
Konstanta
Variabel konstan adalah variabel yang nilainya tidak dapat diubah setelah ditetapkan. Sebuah konstanta dalam bahasa pemrograman Go dideklarasikan dengan menggunakan kata kunci “const”
Buat file bernama constant.go dan dengan kode berikut
package main import ("fmt") func main() { const b =10 fmt.Println(b) b = 30 fmt.Println(b) }
Jalankan go run Constant.go untuk melihat hasilnya
.constant.go:7:4: cannot assign to b
Untuk Contoh Lingkaran
Loop digunakan untuk mengeksekusi blok pernyataan berulang kali berdasarkan suatu kondisi. Sebagian besar bahasa pemrograman menyediakan 3 jenis perulangan – for, while, do while. Namun bahasa pemrograman Go hanya mendukung for loop.
Sintaks dari perulangan for Golang adalah
for initialisation_expression; evaluation_expression; iteration_expression{ // one or more statement }
Inisialisasi_ekspresi dieksekusi pertama kali (dan hanya sekali) dalam loop for Golang.
Kemudian evaluasi_ekspresi dievaluasi dan jika benar, kode di dalam blok akan dieksekusi.
Id iterasi_ekspresi dijalankan, dan ekspresi_evaluasi dievaluasi lagi. Jika benar, blok pernyataan akan dieksekusi lagi. Ini akan berlanjut hingga ekspresi_evaluasi menjadi salah.
Salin program di bawah ini ke dalam file dan jalankan untuk melihat loop Golang mencetak angka dari 1 hingga 5
package main import "fmt" func main() { var i int for i = 1; i <= 5; i++ { fmt.Println(i) } }
Keluaran adalah
1 2 3 4 5
Jika lagi
If else merupakan pernyataan bersyarat. Sinaksnya adalah
if condition{ // statements_1 }else{ // statements_2 }
Di sini kondisi dievaluasi dan jika benar, statement_1 akan dieksekusi, jika tidak, statement_2 akan dieksekusi.
Anda juga dapat menggunakan pernyataan if tanpa else. Anda juga dapat merangkai pernyataan if else. Program di bawah ini akan menjelaskan lebih lanjut tentang if else.
Jalankan program di bawah ini. Ia memeriksa apakah suatu angka, x, kurang dari 10. Jika ya, ia akan mencetak “x kurang dari 10”
package main import "fmt" func main() { var x = 50 if x < 10 { //Executes if x < 10 fmt.Println("x is less than 10") } }
Di sini karena nilai x lebih besar dari 10, pernyataan di dalam kondisi blok if tidak akan dieksekusi.
Sekarang lihat program di bawah ini. Dalam tutorial bahasa pemrograman Go ini, kita memiliki blok else yang akan dieksekusi jika evaluasi if gagal.
package main import "fmt" func main() { var x = 50 if x < 10 { //Executes if x is less than 10 fmt.Println("x is less than 10") } else { //Executes if x >= 10 fmt.Println("x is greater than or equals 10") } }
Program ini akan memberi Anda keluaran
x is greater than or equals 10
Sekarang dalam tutorial Go ini, kita akan melihat sebuah program dengan beberapa blok if else (dirangkai if else). Jalankan contoh Go di bawah ini. Ia memeriksa apakah suatu angka kurang dari 10 atau antara 10-90 atau lebih besar dari 90.
package main import "fmt" func main() { var x = 100 if x < 10 { //Executes if x is less than 10 fmt.Println("x is less than 10") } else if x >= 10 && x <= 90 { //Executes if x >= 10 and x<=90 fmt.Println("x is between 10 and 90") } else { //Executes if both above cases fail i.e x>90 fmt.Println("x is greater than 90") } }
Di sini pertama-tama kondisi if memeriksa apakah x kurang dari 10 dan ternyata tidak. Jadi ia memeriksa kondisi berikutnya (jika lain) apakah antara 10 dan 90 yang juga salah. Jadi ia kemudian mengeksekusi blok di bawah bagian else yang memberikan output
x is greater than 90
Beralih
Switch adalah pernyataan kondisional lainnya. Pernyataan switch mengevaluasi ekspresi dan hasilnya dibandingkan dengan sekumpulan nilai yang tersedia (kasus). Setelah kecocokan ditemukan, pernyataan yang terkait dengan kecocokan (kasus) tersebut dieksekusi. Jika tidak ada kecocokan yang ditemukan, tidak ada yang akan dieksekusi. Anda juga dapat menambahkan kasus default ke switch yang akan dieksekusi jika tidak ada kecocokan lain yang ditemukan. Sintaks saklarnya adalah
switch expression { case value_1: statements_1 case value_2: statements_2 case value_n: statements_n default: statements_default }
Di sini nilai ekspresi dibandingkan dengan nilai dalam setiap kasus. Setelah kecocokan ditemukan, pernyataan yang terkait dengan kasus tersebut akan dieksekusi. Jika tidak ditemukan kecocokan, pernyataan di bagian default akan dieksekusi.
Jalankan program di bawah ini
package main import "fmt" func main() { a,b := 2,1 switch a+b { case 1: fmt.Println("Sum is 1") case 2: fmt.Println("Sum is 2") case 3: fmt.Println("Sum is 3") default: fmt.Println("Printing default") } }
Anda akan mendapatkan output sebagai
Sum is 3
Ubah nilai a dan b menjadi 3 dan hasilnya adalah
Printing default
Anda juga dapat memiliki beberapa nilai dalam satu kasus dengan memisahkannya dengan koma.
Array
Array mewakili ukuran tetap, bernama urutan elemen dari tipe yang sama. Anda tidak dapat memiliki array yang berisi bilangan bulat dan karakter di dalamnya. Anda tidak dapat mengubah ukuran array setelah Anda menentukan ukurannya.
Sintaks untuk mendeklarasikan array adalah
var arrayname [size] type
Setiap elemen array dapat diberi nilai menggunakan sintaksis
arrayname [index] = value
Indeks array dimulai dari 0 hingga ukuran-1.
Anda dapat menetapkan nilai ke elemen array selama deklarasi menggunakan sintaksis
arrayname := [size] type {value_0,value_1,…,value_size-1}
Anda juga dapat mengabaikan parameter ukuran saat mendeklarasikan array dengan nilai dengan mengganti ukuran dengan ... dan kompiler akan menemukan panjang dari jumlah nilai. Sintaksnya adalah
arrayname := […] type {value_0,value_1,…,value_size-1}
Anda dapat mengetahui panjang array dengan menggunakan sintaks
len(arrayname)
Jalankan contoh Go di bawah ini untuk memahami array
package main import "fmt" func main() { var numbers [3] string //Declaring a string array of size 3 and adding elements numbers[0] = "One" numbers[1] = "Two" numbers[2] = "Three" fmt.Println(numbers[1]) //prints Two fmt.Println(len(numbers)) //prints 3 fmt.Println(numbers) // prints [One Two Three] directions := [...] int {1,2,3,4,5} // creating an integer array and the size of the array is defined by the number of elements fmt.Println(directions) //prints [1 2 3 4 5] fmt.Println(len(directions)) //prints 5 //Executing the below commented statement prints invalid array index 5 (out of bounds for 5-element array) //fmt.Println(directions[5]) }
Keluaran
Two 3 [One Two Three] [1 2 3 4 5] 5
Fungsi Irisan dan Tambahkan Golang
Irisan adalah bagian atau segmen dari array. Atau itu adalah tampilan atau tampilan sebagian dari array yang mendasarinya yang ditunjuknya. Anda dapat mengakses elemen irisan menggunakan nama irisan dan nomor indeks seperti yang Anda lakukan dalam array. Anda tidak dapat mengubah panjang array, namun Anda dapat mengubah ukuran irisan.
Isi dari sebuah irisan sebenarnya adalah penunjuk ke elemen array. Itu berarti jika Anda mengubah elemen apa pun dalam sebuah irisan, konten array yang mendasarinya juga akan terpengaruh.
Sintaks untuk membuat irisan adalah
var slice_name [] type = array_name[start:end]
Ini akan membuat irisan bernama irisan_nama dari array bernama array_name dengan elemen pada indeks mulai hingga akhir-1.
Sekarang dalam tutorial Golang ini, kita akan menjalankan program di bawah ini. Program ini akan membuat potongan dari array dan mencetaknya. Selain itu, Anda dapat melihat bahwa mengubah konten dalam irisan akan mengubah array sebenarnya.
package main import "fmt" func main() { // declaring array a := [5] string {"one", "two", "three", "four", "five"} fmt.Println("Array after creation:",a) var b [] string = a[1:4] //created a slice named b fmt.Println("Slice after creation:",b) b[0]="changed" // changed the slice data fmt.Println("Slice after modifying:",b) fmt.Println("Array after slice modification:",a) }
Ini akan mencetak hasil sebagai
Array after creation: [one two three four five] Slice after creation: [two three four] Slice after modifying: [changed three four] Array after slice modification: [one changed three four five]
Ada fungsi tertentu seperti Golang len, Golang append yang dapat Anda terapkan pada irisan
len(nama_irisan) – mengembalikan panjang irisan
tambahkan(slice_name, value_1, value_2) – Golang append digunakan untuk menambahkan value_1 dan value_2 ke irisan yang sudah ada.
tambahkan(slice_nale1,slice_name2…) – menambahkan nama_slice2 ke nama_slice1
Jalankan program berikut.
package main import "fmt" func main() { a := [5] string {"1","2","3","4","5"} slice_a := a[1:3] b := [5] string {"one","two","three","four","five"} slice_b := b[1:3] fmt.Println("Slice_a:", slice_a) fmt.Println("Slice_b:", slice_b) fmt.Println("Length of slice_a:", len(slice_a)) fmt.Println("Length of slice_b:", len(slice_b)) slice_a = append(slice_a,slice_b...) // appending slice fmt.Println("New Slice_a after appending slice_b :", slice_a) slice_a = append(slice_a,"text1") // appending value fmt.Println("New Slice_a after appending text1 :", slice_a) }
Outputnya akan menjadi
Slice_a: [2 3] Slice_b: [two three] Length of slice_a: 2 Length of slice_b: 2 New Slice_a after appending slice_b : [2 3 two three] New Slice_a after appending text1 : [2 3 two three text1]
Program pertama-tama membuat 2 irisan dan mencetak panjangnya. Kemudian ia menambahkan satu irisan ke irisan lainnya dan kemudian menambahkan string ke irisan yang dihasilkan.
Fungsi
Suatu fungsi mewakili blok pernyataan yang melakukan tugas tertentu. Deklarasi fungsi memberi tahu kita nama fungsi, tipe kembalian, dan parameter input. Definisi fungsi mewakili kode yang terdapat dalam fungsi. Sintaks untuk mendeklarasikan fungsi adalah
func function_name(parameter_1 type, parameter_n type) return_type { //statements }
Parameter dan tipe pengembalian bersifat opsional. Selain itu, Anda dapat mengembalikan beberapa nilai dari suatu fungsi.
Sekarang dalam tutorial Golang ini, mari kita jalankan contoh Golang berikut. Di sini, fungsi bernama calc akan menerima 2 angka dan melakukan penjumlahan dan pengurangan serta mengembalikan kedua nilai tersebut.
package main import "fmt" //calc is the function name which accepts two integers num1 and num2 //(int, int) says that the function returns two values, both of integer type. func calc(num1 int, num2 int)(int, int) { sum := num1 + num2 diff := num1 - num2 return sum, diff } func main() { x,y := 15,10 //calls the function calc with x and y an d gets sum, diff as output sum, diff := calc(x,y) fmt.Println("Sum",sum) fmt.Println("Diff",diff) }
Outputnya akan menjadi
Sum 25 Diff 5
Paket Kami.
Paket digunakan untuk mengatur kode. Dalam proyek besar, tidak mungkin menulis kode dalam satu file. Bahasa pemrograman Go memungkinkan kita mengatur kode dalam paket yang berbeda. Hal ini meningkatkan keterbacaan dan penggunaan kembali kode. Program Go yang dapat dieksekusi harus berisi paket bernama main dan eksekusi program dimulai dari fungsi bernama main. Anda dapat mengimpor paket lain ke program kami menggunakan sintaks
import package_name
Kita akan melihat dan membahas dalam tutorial Golang ini, cara membuat dan menggunakan paket dalam contoh Golang berikut.
Langkah 1) Buat file bernama package_example.go dan tambahkan kode di bawah ini
package main import "fmt" //the package to be created import "calculation" func main() { x,y := 15,10 //the package will have function Do_add() sum := calculation.Do_add(x,y) fmt.Println("Sum",sum) }
Dalam program di atas, fmt adalah paket yang disediakan oleh bahasa pemrograman Go terutama untuk keperluan I/O. Juga, Anda dapat melihat paket bernama perhitungan. Di dalam main() Anda dapat melihat langkah jumlah := perhitungan.Lakukan_tambahan(x,y). Artinya Anda menjalankan fungsi Do_add dari penghitungan paket.
Langkah 2) Pertama, Anda harus membuat penghitungan paket di dalam folder dengan nama yang sama di bawah folder src saat bepergian. Jalur go yang terinstal dapat ditemukan dari variabel PATH.
Untuk Mac, temukan jalurnya dengan menjalankan echo $PATH
Jadi jalurnya adalah /usr/local/go
Untuk windows, temukan path dengan menjalankan echo %GOROOT%
Di sini jalurnya adalah C:\Go\
Langkah 3) Arahkan ke folder src (/usr/local/go/src untuk mac dan C:\Go\src untuk windows). Sekarang dari kode tersebut, nama paketnya adalah Calculation. Go mengharuskan paket tersebut ditempatkan di direktori dengan nama yang sama di bawah direktori src. Buat direktori bernama Calculation di folder src.
Langkah 4) Buat file bernama calc.go (Anda dapat memberi nama apa pun, tetapi nama paket dalam kode itu penting. Di sini seharusnya perhitungannya) di dalam direktori perhitungan dan tambahkan kode di bawah ini
package calculation func Do_add(num1 int, num2 int)(int) { sum := num1 + num2 return sum }
Langkah 5) Jalankan perintah go install dari direktori perhitungan yang akan mengkompilasi calc.go.
Langkah 6) Sekarang kembali ke package_example.go dan jalankan go run package_example.go. Outputnya adalah Jumlah 25.
Perhatikan bahwa nama fungsi Do_add dimulai dengan huruf kapital. Hal ini karena di Go jika nama fungsinya dimulai dengan huruf kapital berarti program lain dapat melihat (mengaksesnya) jika tidak, program lain tidak dapat mengaksesnya. Jika nama fungsinya do_add , Anda akan mendapatkan kesalahan
tidak dapat merujuk ke nama yang tidak diekspor kalkulasi.kalk..
Tunda dan susun penundaan
Pernyataan penangguhan digunakan untuk menunda eksekusi pemanggilan fungsi hingga fungsi yang berisi pernyataan penangguhan menyelesaikan eksekusi.
Mari kita pelajari ini dengan sebuah contoh:
package main import "fmt" func sample() { fmt.Println("Inside the sample()") } func main() { //sample() will be invoked only after executing the statements of main() defer sample() fmt.Println("Inside the main()") }
Outputnya akan menjadi
Inside the main() Inside the sample()
Di sini eksekusi sample() ditunda hingga eksekusi fungsi terlampir (main()) selesai.
Penundaan penangguhan menggunakan beberapa pernyataan penangguhan. Misalkan Anda memiliki beberapa pernyataan defer di dalam suatu fungsi. Go menempatkan semua panggilan fungsi yang ditangguhkan ke dalam tumpukan, dan setelah fungsi terlampir kembali, fungsi yang ditumpuk akan dieksekusi di Urutan Masuk Terakhir Keluar Pertama (LIFO). Anda dapat melihatnya pada contoh di bawah ini.
Jalankan kode di bawah ini
package main import "fmt" func display(a int) { fmt.Println(a) } func main() { defer display(1) defer display(2) defer display(3) fmt.Println(4) }
Outputnya akan menjadi
4 3 2 1
Di sini kode di dalam main() dieksekusi terlebih dahulu, dan kemudian pemanggilan fungsi yang ditangguhkan dieksekusi dalam urutan terbalik, yaitu 4, 3,2,1.
pointer
Sebelum menjelaskan pointer, mari kita bahas dulu operator '&'. Operator '&' digunakan untuk mendapatkan alamat suatu variabel. Artinya '&a' akan mencetak alamat memori variabel a.
Dalam tutorial Golang ini, kita akan menjalankan program di bawah ini untuk menampilkan nilai suatu variabel dan alamat variabel tersebut
package main import "fmt" func main() { a := 20 fmt.Println("Address:",&a) fmt.Println("Value:",a) }
Hasilnya akan
Address: 0xc000078008 Value: 20
Variabel penunjuk menyimpan alamat memori variabel lain. Anda dapat menentukan pointer menggunakan sintaks
var variable_name *type
Tanda bintang (*) yang mewakili variabel adalah sebuah pointer. Anda akan memahami lebih lanjut dengan menjalankan program di bawah ini
package main import "fmt" func main() { //Create an integer variable a with value 20 a := 20 //Create a pointer variable b and assigned the address of a var b *int = &a //print address of a(&a) and value of a fmt.Println("Address of a:",&a) fmt.Println("Value of a:",a) //print b which contains the memory address of a i.e. &a fmt.Println("Address of pointer b:",b) //*b prints the value in memory address which b contains i.e. the value of a fmt.Println("Value of pointer b",*b) //increment the value of variable a using the variable b *b = *b+1 //prints the new value using a and *b fmt.Println("Value of pointer b",*b) fmt.Println("Value of a:",a)}
Outputnya akan menjadi
Address of a: 0x416020 Value of a: 20 Address of pointer b: 0x416020 Value of pointer b 20 Value of pointer b 21 Value of a: 21
Struktur
Struktur adalah tipe data yang ditentukan pengguna yang berisi satu elemen lagi dengan tipe yang sama atau berbeda.
Menggunakan struktur adalah proses 2 langkah.
Pertama, buat (deklarasikan) tipe struktur
Kedua, buat variabel jenis itu untuk menyimpan nilai.
Struktur terutama digunakan ketika Anda ingin menyimpan data terkait secara bersamaan.
Pertimbangkan sepotong informasi karyawan yang memiliki nama, usia, dan alamat. Anda dapat mengatasinya dengan 2 cara
Buat 3 array – satu array menyimpan nama karyawan, satu menyimpan umur, dan yang ketiga menyimpan umur.
Deklarasikan tipe struktur dengan 3 bidang- nama, alamat, dan usia. Buat array tipe struktur di mana setiap elemen adalah objek struktur yang memiliki nama, alamat, dan umur.
Pendekatan pertama tidak efisien. Dalam skenario seperti ini, struktur lebih nyaman.
Sintaks untuk mendeklarasikan suatu struktur adalah
type structname struct { variable_1 variable_1_type variable_2 variable_2_type variable_n variable_n_type }
Contoh deklarasi struktur adalah
type emp struct { name string address string age int }
Di sini tipe baru yang ditentukan pengguna bernama emp dibuat. Sekarang, Anda dapat membuat variabel bertipe emp menggunakan sintaksis
var variable_name struct_name
Contohnya adalah
var empdata1 emp
Anda dapat menetapkan nilai untuk empdata1 sebagai
empdata1.name = "John" empdata1.address = "Street-1, Bangalore" empdata1.age = 30
Anda juga dapat membuat variabel struktur dan menetapkan nilai berdasarkan
empdata2 := emp{"Raj", "Building-1, Delhi", 25}
Di sini, Anda perlu menjaga urutan elemen. Raj akan dipetakan ke nama, elemen berikutnya ke alamat, dan elemen terakhir ke usia.
Jalankan kode di bawah ini
package main import "fmt" //declared the structure named emp type emp struct { name string address string age int } //function which accepts variable of emp type and prints name property func display(e emp) { fmt.Println(e.name) } func main() { // declares a variable, empdata1, of the type emp var empdata1 emp //assign values to members of empdata1 empdata1.name = "John" empdata1.address = "Street-1, London" empdata1.age = 30 //declares and assign values to variable empdata2 of type emp empdata2 := emp{"Raj", "Building-1, Paris", 25} //prints the member name of empdata1 and empdata2 using display function display(empdata1) display(empdata2) }
Keluaran
John Raj
Metode (bukan fungsi)
Metode adalah fungsi dengan argumen penerima. Archisecara teknis, itu berada di antara kata kunci func dan nama metode. Sintaks suatu metode adalah
func (variable variabletype) methodName(parameter1 paramether1type) { }
Mari kita ubah contoh program di atas untuk menggunakan metode, bukan fungsi.
package main import "fmt" //declared the structure named emp type emp struct { name string address string age int } //Declaring a function with receiver of the type emp func(e emp) display() { fmt.Println(e.name) } func main() { //declaring a variable of type emp var empdata1 emp //Assign values to members empdata1.name = "John" empdata1.address = "Street-1, Lodon" empdata1.age = 30 //declaring a variable of type emp and assign values to members empdata2 := emp { "Raj", "Building-1, Paris", 25} //Invoking the method using the receiver of the type emp // syntax is variable.methodname() empdata1.display() empdata2.display() }
Go bukanlah bahasa berorientasi objek dan tidak memiliki konsep kelas. Metode memberikan gambaran tentang apa yang Anda lakukan dalam program berorientasi objek di mana fungsi suatu kelas dipanggil menggunakan sintaks objectname.functionname()
Concurrency
Go mendukung eksekusi tugas secara bersamaan. Artinya Go dapat mengeksekusi beberapa tugas secara bersamaan. Hal ini berbeda dengan konsep paralelisme. Dalam paralelisme, tugas dibagi menjadi beberapa subtugas kecil dan dieksekusi secara paralel. Namun dalam konkurensi, beberapa tugas dieksekusi secara bersamaan. Konkurensi dicapai dalam Go menggunakan Goroutine dan Channel.
goroutine
Goroutine adalah fungsi yang dapat berjalan bersamaan dengan fungsi lainnya. Biasanya ketika suatu fungsi dipanggil, kontrol akan ditransfer ke fungsi yang dipanggil, dan setelah eksekusi selesai, kontrol kembali ke fungsi pemanggil. Fungsi pemanggil kemudian melanjutkan eksekusinya. Fungsi pemanggil menunggu fungsi yang dipanggil menyelesaikan eksekusi sebelum melanjutkan dengan pernyataan lainnya.
Namun dalam kasus goroutine, fungsi pemanggil tidak akan menunggu hingga eksekusi fungsi yang dipanggil selesai. Ini akan terus dieksekusi dengan pernyataan berikutnya. Anda dapat memiliki beberapa goroutine dalam sebuah program.
Selain itu, program utama akan keluar setelah selesai mengeksekusi pernyataannya dan tidak akan menunggu selesainya goroutine yang dipanggil.
Goroutine dipanggil menggunakan kata kunci go diikuti dengan pemanggilan fungsi.
Example
go add(x,y)
Anda akan memahami goroutine dengan contoh Golang di bawah ini. Jalankan program di bawah ini
package main import "fmt" func display() { for i:=0; i<5; i++ { fmt.Println("In display") } } func main() { //invoking the goroutine display() go display() //The main() continues without waiting for display() for i:=0; i<5; i++ { fmt.Println("In main") } }
Outputnya akan menjadi
In main In main In main In main In main
Di sini program utama menyelesaikan eksekusi bahkan sebelum goroutine dimulai. display() adalah goroutine yang dipanggil menggunakan sintaksis
go function_name(parameter list)
Pada kode di atas, main() tidak menunggu hingga display() selesai, dan main() menyelesaikan eksekusinya sebelum display() mengeksekusi kodenya. Jadi pernyataan print di dalam display() tidak dicetak.
Sekarang kita memodifikasi program untuk mencetak pernyataan dari display() juga. Kita menambahkan waktu tunda 2 detik pada perulangan for pada main() dan penundaan 1 detik pada perulangan for pada display().
package main import "fmt" import "time" func display() { for i:=0; i<5; i++ { time.Sleep(1 * time.Second) fmt.Println("In display") } } func main() { //invoking the goroutine display() go display() for i:=0; i<5; i++ { time.Sleep(2 * time.Second) fmt.Println("In main") } }
Outputnya akan agak mirip dengan
In display In main In display In display In main In display In display In main In main In main
Di sini Anda dapat melihat kedua loop dieksekusi secara tumpang tindih karena eksekusi bersamaan.
Saluran
Saluran adalah cara fungsi berkomunikasi satu sama lain. Ini dapat dianggap sebagai media di mana suatu rutin menempatkan data dan diakses oleh rutin lain di server Golang.
Suatu saluran dapat dideklarasikan dengan sintaksis
channel_variable := make(chan datatype)
Contoh:
ch := make(chan int)
Anda dapat mengirim data ke saluran menggunakan sintaksis
channel_variable <- variable_name
Example
ch <- x
Anda dapat menerima data dari saluran menggunakan sintaksis
variable_name := <- channel_variable
Example
y := <- ch
Dalam contoh goroutine bahasa Go di atas, Anda telah melihat program utama tidak menunggu goroutine. Namun hal ini tidak berlaku jika saluran dilibatkan. Misalkan jika goroutine mendorong data ke saluran, main() akan menunggu pernyataan yang menerima data saluran hingga ia mendapatkan datanya.
Anda akan melihatnya pada contoh bahasa Go di bawah ini. Pertama, tulis goroutine normal dan lihat perilakunya. Kemudian modifikasi program untuk menggunakan saluran dan lihat perilakunya.
Jalankan program di bawah ini
package main import "fmt" import "time" func display() { time.Sleep(5 * time.Second) fmt.Println("Inside display()") } func main() { go display() fmt.Println("Inside main()") }
Outputnya akan menjadi
Inside main()
main() menyelesaikan eksekusi dan keluar sebelum goroutine dijalankan. Jadi pencetakan di dalam display() tidak dieksekusi.
Sekarang modifikasi program di atas untuk menggunakan saluran dan lihat perilakunya.
package main import "fmt" import "time" func display(ch chan int) { time.Sleep(5 * time.Second) fmt.Println("Inside display()") ch <- 1234 } func main() { ch := make(chan int) go display(ch) x := <-ch fmt.Println("Inside main()") fmt.Println("Printing x in main() after taking from channel:",x) }
Outputnya akan menjadi
Inside display() Inside main() Printing x in main() after taking from channel: 1234
Di sini yang terjadi adalah main() saat mencapai x := <-ch akan menunggu data di saluran ch. Display() menunggu 5 detik dan kemudian mendorong data ke saluran ch. Main() saat menerima data dari saluran akan dibuka blokirnya dan melanjutkan eksekusinya.
Pengirim yang mendorong data ke saluran dapat memberi tahu penerima bahwa tidak ada lagi data yang akan ditambahkan ke saluran dengan menutup saluran tersebut. Ini terutama digunakan ketika Anda menggunakan loop untuk mendorong data ke saluran. Saluran dapat ditutup menggunakan
close(channel_name)
Dan di sisi penerima, dimungkinkan untuk memeriksa apakah saluran ditutup menggunakan variabel tambahan sambil mengambil data dari saluran menggunakan
variable_name, status := <- channel_variable
Jika statusnya True berarti Anda menerima data dari saluran tersebut. Jika salah, berarti Anda mencoba membaca dari saluran tertutup
Anda juga dapat menggunakan saluran untuk komunikasi antar goroutine. Perlu menggunakan 2 goroutine – yang satu memasukkan data ke saluran dan yang lainnya menerima data dari saluran. Lihat program di bawah ini
package main import "fmt" import "time" //This subroutine pushes numbers 0 to 9 to the channel and closes the channel func add_to_channel(ch chan int) { fmt.Println("Send data") for i:=0; i<10; i++ { ch <- i //pushing data to channel } close(ch) //closing the channel } //This subroutine fetches data from the channel and prints it. func fetch_from_channel(ch chan int) { fmt.Println("Read data") for { //fetch data from channel x, flag := <- ch //flag is true if data is received from the channel //flag is false when the channel is closed if flag == true { fmt.Println(x) }else{ fmt.Println("Empty channel") break } } } func main() { //creating a channel variable to transport integer values ch := make(chan int) //invoking the subroutines to add and fetch from the channel //These routines execute simultaneously go add_to_channel(ch) go fetch_from_channel(ch) //delay is to prevent the exiting of main() before goroutines finish time.Sleep(5 * time.Second) fmt.Println("Inside main()") }
Di sini ada 2 subrutin, satu mendorong data ke saluran dan yang lain mencetak data ke saluran. Fungsi add_to_channel menambahkan angka dari 0 hingga 9 dan menutup saluran. Secara bersamaan fungsi fetch_from_channel menunggu di
x, flag := <- ch dan setelah data tersedia, data akan dicetak. Ini keluar ketika benderanya salah yang berarti saluran ditutup.
Penantian di main() diberikan untuk mencegah keluarnya main() hingga goroutine menyelesaikan eksekusi.
Jalankan kode dan lihat hasilnya sebagai
Read data Send data 0 1 2 3 4 5 6 7 8 9 Empty channel Inside main()
Pilih
Pilih dapat dilihat sebagai pernyataan peralihan yang berfungsi pada saluran. Di sini pernyataan kasus akan menjadi operasi saluran. Biasanya setiap pernyataan kasus akan dibacakan secara percobaan dari saluran tersebut. Ketika salah satu kasus sudah siap (saluran dibaca), maka pernyataan yang terkait dengan kasus tersebut dieksekusi. Jika beberapa kasus sudah siap, ia akan memilih satu kasus secara acak. Anda dapat memiliki kasus default yang dijalankan jika tidak ada kasus yang siap.
Mari kita lihat kode di bawah ini
package main import "fmt" import "time" //push data to channel with a 4 second delay func data1(ch chan string) { time.Sleep(4 * time.Second) ch <- "from data1()" } //push data to channel with a 2 second delay func data2(ch chan string) { time.Sleep(2 * time.Second) ch <- "from data2()" } func main() { //creating channel variables for transporting string values chan1 := make(chan string) chan2 := make(chan string) //invoking the subroutines with channel variables go data1(chan1) go data2(chan2) //Both case statements wait for data in the chan1 or chan2. //chan2 gets data first since the delay is only 2 sec in data2(). //So the second case will execute and exits the select block select { case x := <-chan1: fmt.Println(x) case y := <-chan2: fmt.Println(y) } }
Mengeksekusi program di atas akan menghasilkan output:
from data2()
Di sini pernyataan pilih menunggu data tersedia di saluran mana pun. data2() menambahkan data ke saluran setelah tidur selama 2 detik yang akan menyebabkan kasus kedua dijalankan.
Tambahkan case default ke pilihan di program yang sama dan lihat hasilnya. Di sini, saat mencapai blok yang dipilih, jika tidak ada data yang siap di saluran, blok tersebut akan menjalankan blok default tanpa menunggu data tersedia di saluran mana pun.
package main import "fmt" import "time" //push data to channel with a 4 second delay func data1(ch chan string) { time.Sleep(4 * time.Second) ch <- "from data1()" } //push data to channel with a 2 second delay func data2(ch chan string) { time.Sleep(2 * time.Second) ch <- "from data2()" } func main() { //creating channel variables for transporting string values chan1 := make(chan string) chan2 := make(chan string) //invoking the subroutines with channel variables go data1(chan1) go data2(chan2) //Both case statements check for data in chan1 or chan2. //But data is not available (both routines have a delay of 2 and 4 sec) //So the default block will be executed without waiting for data in channels. select { case x := <-chan1: fmt.Println(x) case y := <-chan2: fmt.Println(y) default: fmt.Println("Default case executed") } }
Program ini akan memberikan output:
Default case executed
Hal ini karena ketika blok pilih tercapai, tidak ada saluran yang memiliki data untuk dibaca. Jadi, kasus default dijalankan.
mutex
Mutex adalah kependekan dari mutual exclusion. Mutex digunakan ketika Anda tidak ingin mengizinkan suatu sumber daya diakses oleh beberapa subrutin secara bersamaan. Mutex memiliki 2 metode – Lock dan Unlock. Mutex terdapat dalam paket sinkronisasi. Jadi, Anda harus mengimpor paket sinkronisasi. Pernyataan yang harus dijalankan secara eksklusif dapat ditempatkan di dalam mutex.Lock() dan mutex.Unlock().
Mari kita belajar mutex dengan contoh menghitung berapa kali sebuah loop dieksekusi. Dalam program ini kita mengharapkan rutin untuk menjalankan loop 10 kali dan hitungannya disimpan dalam jumlah. Anda memanggil rutin ini 3 kali sehingga jumlah totalnya harus 30. Jumlah tersebut disimpan dalam jumlah variabel global.
Pertama, Anda menjalankan program tanpa mutex
package main import "fmt" import "time" import "strconv" import "math/rand" //declare count variable, which is accessed by all the routine instances var count = 0 //copies count to temp, do some processing(increment) and store back to count //random delay is added between reading and writing of count variable func process(n int) { //loop incrementing the count by 10 for i := 0; i < 10; i++ { time.Sleep(time.Duration(rand.Int31n(2)) * time.Second) temp := count temp++ time.Sleep(time.Duration(rand.Int31n(2)) * time.Second) count = temp } fmt.Println("Count after i="+strconv.Itoa(n)+" Count:", strconv.Itoa(count)) } func main() { //loop calling the process() 3 times for i := 1; i < 4; i++ { go process(i) } //delay to wait for the routines to complete time.Sleep(25 * time.Second) fmt.Println("Final Count:", count) }
Lihat hasilnya
Count after i=1 Count: 11 Count after i=3 Count: 12 Count after i=2 Count: 13 Final Count: 13
Hasilnya mungkin berbeda ketika Anda menjalankannya tetapi hasil akhirnya tidak akan menjadi 30.
Di sini yang terjadi adalah 3 goroutine mencoba meningkatkan jumlah loop yang disimpan dalam variabel count. Misalkan saat ini hitungannya adalah 5 dan goroutine1 akan menambah hitungannya menjadi 6. Langkah utamanya meliputi
Jumlah salinan ke suhu
Kenaikan suhu
Simpan suhu kembali untuk dihitung
Misalkan segera setelah melakukan langkah 3 dengan goroutine1; goroutine lain mungkin memiliki nilai lama, katakanlah 3 melakukan langkah di atas dan menyimpan 4 kembali, dan ini salah. Hal ini dapat dicegah dengan menggunakan mutex yang menyebabkan rutin lainnya menunggu ketika salah satu rutin sudah menggunakan variabel tersebut.
Sekarang Anda akan menjalankan program dengan mutex. Di sini 3 langkah yang disebutkan di atas dijalankan dalam mutex.
package main import "fmt" import "time" import "sync" import "strconv" import "math/rand" //declare a mutex instance var mu sync.Mutex //declare count variable, which is accessed by all the routine instances var count = 0 //copies count to temp, do some processing(increment) and store back to count //random delay is added between reading and writing of count variable func process(n int) { //loop incrementing the count by 10 for i := 0; i < 10; i++ { time.Sleep(time.Duration(rand.Int31n(2)) * time.Second) //lock starts here mu.Lock() temp := count temp++ time.Sleep(time.Duration(rand.Int31n(2)) * time.Second) count = temp //lock ends here mu.Unlock() } fmt.Println("Count after i="+strconv.Itoa(n)+" Count:", strconv.Itoa(count)) } func main() { //loop calling the process() 3 times for i := 1; i < 4; i++ { go process(i) } //delay to wait for the routines to complete time.Sleep(25 * time.Second) fmt.Println("Final Count:", count) }
Sekarang hasilnya adalah
Count after i=3 Count: 21 Count after i=2 Count: 28 Count after i=1 Count: 30 Final Count: 30
Di sini kita mendapatkan hasil yang diharapkan sebagai hasil akhir. Karena pernyataan membaca, menambah dan menulis kembali hitungan dieksekusi dalam mutex.
Menangani kesalahan
Kesalahan adalah kondisi abnormal seperti menutup file yang tidak dibuka, membuka file yang tidak ada, dll. Fungsi biasanya mengembalikan kesalahan sebagai nilai kembalian terakhir.
Contoh di bawah ini menjelaskan lebih lanjut tentang kesalahan tersebut.
package main import "fmt" import "os" //function accepts a filename and tries to open it. func fileopen(name string) { f, er := os.Open(name) //er will be nil if the file exists else it returns an error object if er != nil { fmt.Println(er) return }else{ fmt.Println("file opened", f.Name()) } } func main() { fileopen("invalid.txt") }
output akan:
open /invalid.txt: no such file or directory
Di sini kami mencoba membuka file yang tidak ada, dan mengembalikan kesalahan ke variabel er. Jika file tersebut valid, maka kesalahannya akan nol
Kesalahan khusus
Dengan menggunakan fitur ini, Anda dapat membuat kesalahan khusus. Hal ini dilakukan dengan menggunakan paket kesalahan New(). Kami akan menulis ulang program di atas untuk memanfaatkan kesalahan khusus.
Jalankan program di bawah ini
package main import "fmt" import "os" import "errors" //function accepts a filename and tries to open it. func fileopen(name string) (string, error) { f, er := os.Open(name) //er will be nil if the file exists else it returns an error object if er != nil { //created a new error object and returns it return "", errors.New("Custom error message: File name is wrong") }else{ return f.Name(),nil } } func main() { //receives custom error or nil after trying to open the file filename, error := fileopen("invalid.txt") if error != nil { fmt.Println(error) }else{ fmt.Println("file opened", filename) } }
output akan:
Custom error message:File name is wrong
Di sini area() mengembalikan luas persegi. Jika inputnya kurang dari 1 maka area() mengembalikan pesan kesalahan.
Membaca file
File digunakan untuk menyimpan data. Go memungkinkan kita membaca data dari file
Pertama buat file, data.txt, di direktori Anda saat ini dengan konten di bawah ini.
Line one Line two Line three
Sekarang jalankan program di bawah ini untuk melihatnya mencetak konten seluruh file sebagai output
package main import "fmt" import "io/ioutil" func main() { data, err := ioutil.ReadFile("data.txt") if err != nil { fmt.Println("File reading error", err) return } fmt.Println("Contents of file:", string(data)) }
Di sini datanya, err := ioutil.ReadFile(“data.txt”) membaca data dan mengembalikan urutan byte. Saat mencetak, itu diubah ke format string.
Menulis file
Anda akan melihatnya dengan sebuah program
package main import "fmt" import "os" func main() { f, err := os.Create("file1.txt") if err != nil { fmt.Println(err) return } l, err := f.WriteString("Write Line one") if err != nil { fmt.Println(err) f.Close() return } fmt.Println(l, "bytes written") err = f.Close() if err != nil { fmt.Println(err) return } }
Di sini file dibuat, test.txt. Jika file sudah ada maka isi file akan terpotong. Writeline() digunakan untuk menulis konten ke file. Setelah itu, Anda menutup file menggunakan Close().
Lembar Curang
Dalam tutorial Go ini, kami membahas,
Tema | Description | Sintaksis |
---|---|---|
Tipe dasar | Numerik, string, bool | |
Variabel | Deklarasikan dan tetapkan nilai ke variabel | tipe nama_variabel var var nama_variabel tipe = nilai var nama_variabel1, nama_variabel2 = nilai1, nilai2 nama_variabel := nilai |
Konstanta | Variabel yang nilainya tidak dapat diubah setelah ditetapkan | variabel const = nilai |
Untuk Loop | Jalankan pernyataan dalam satu lingkaran. | untuk inisialisasi_ekspresi; evaluasi_ekspresi; iterasi_ekspresi{ // satu atau lebih pernyataan } |
Jika lagi | Itu adalah pernyataan bersyarat | jika kondisi{ // pernyataan_1 } Else { // pernyataan_2 } |
saklar | Pernyataan bersyarat dengan banyak kasus | ganti ekspresi { nilai kasus_1: pernyataan_1 nilai kasus_2: pernyataan_2 nilai kasus_n: pernyataan_n default: pernyataan_default } |
susunan | Ukuran tetap bernama urutan elemen dengan tipe yang sama | nama array := [ukuran] ketik {nilai_0,nilai_1,…,ukuran_nilai-1} |
Iris | Bagian atau segmen dari sebuah array | var nama_irisan [] ketik = nama_array[mulai:akhir] |
Fungsi | Blok pernyataan yang melakukan tugas tertentu | func function_name(tipe_parameter_1, tipe_parameter_n) return_type { //pernyataan } |
Paket Kami. | Digunakan untuk mengatur kode. Meningkatkan keterbacaan dan penggunaan kembali kode | impor paket_nam |
Menunda | Menunda eksekusi suatu fungsi hingga fungsi yang memuatnya menyelesaikan eksekusi | tunda nama_fungsi(daftar_parameter) |
pointer | Menyimpan alamat memori variabel lain. | var nama_variabel *ketik |
Structure | Tipe data yang ditentukan pengguna yang berisi satu elemen lagi dengan tipe yang sama atau berbeda | ketik nama struct struct { variabel_1 variabel_1_tipe variabel_2 variabel_2_tipe variabel_n variabel_n_tipe } |
metode | Metode adalah fungsi dengan argumen penerima | func (tipe variabel variabel) nama metode(daftar_parameter) { } |
goroutine | Fungsi yang dapat berjalan bersamaan dengan fungsi lainnya. | buka nama_fungsi(daftar_parameter) |
Saluran | Cara bagi fungsi untuk berkomunikasi satu sama lain. Suatu media dimana suatu rutin menempatkan data dan diakses oleh rutin lainnya. | Menyatakan: ch := buat(chan int) Kirim data ke saluran: variabel_saluran <- nama_variabel Terima dari saluran: nama_variabel := <- variabel_saluran |
Pilih | Ganti pernyataan yang berfungsi pada saluran. Pernyataan kasus akan menjadi operasi saluran. Ketika salah satu saluran sudah siap dengan data, maka pernyataan yang terkait dengan kasus tersebut dijalankan | Pilih { kasus x := <-chan1: fmt.Println(x) kasus y := <-chan2: fmt.Println(y) } |
mutex | Mutex digunakan ketika Anda tidak ingin mengizinkan sumber daya diakses oleh beberapa subrutin secara bersamaan. Mutex memiliki 2 metode – Kunci dan Buka Kunci | mutex.Kunci() //pernyataan mutex.Buka Kunci(). |
Membaca file | Membaca data dan mengembalikan urutan byte. | Data, err := ioutil.ReadFile(nama file) |
Tulis berkas | Menulis data ke file | aku, err := f.WriteString(text_to_write) |