1. Apa itu Pernyataan goto
Pernyataan goto
adalah salah satu struktur kontrol dalam bahasa C yang digunakan untuk melompat ke label tertentu dan mengatur alur program. Berbeda dengan banyak struktur kontrol lainnya, goto
memungkinkan melompat ke lokasi mana pun dalam program, sehingga alur kontrol dapat diatur secara fleksibel. Namun, penggunaan yang tidak teratur dapat berdampak negatif pada keterbacaan dan pemeliharaan kode, sehingga perlu digunakan dengan hati-hati.
Sintaks Dasar goto
Sintaks goto
adalah sebagai berikut:
goto label;
Ketika goto
dipanggil, alur program akan melompat ke lokasi di mana label yang sesuai didefinisikan. Label adalah pengenal yang ditulis tepat sebelum pernyataan seperti berikut:
nama_label:
Sebagai contoh, mari kita lihat program sederhana untuk memahami cara kerja goto
.
Contoh Penggunaan goto
#include <stdio.h>
int main() {
int i = 0;
start: // Definisi label
printf("Nilai i: %dn", i);
i++;
if (i < 5) {
goto start; // Melompat ke label
}
printf("Loop selesai\n");
return 0;
}
Kode di atas menggunakan goto
untuk melompat ke label start
dan melakukan loop hingga nilai i
menjadi 5. Meskipun goto
dapat digunakan untuk melompat ke lokasi tertentu, penggunaan berlebihan dapat membuat program sulit dipahami, sehingga biasanya digunakan secara hati-hati.
Kegunaan dan Perhatian dalam Menggunakan goto
Dalam bahasa C, goto
dapat dipertimbangkan penggunaannya pada situasi berikut:
- Penanganan Error: Berguna untuk melewati serangkaian proses dan langsung menuju bagian pelepasan sumber daya ketika terjadi error.
- Keluar dari Loop Bersarang: Jika ingin keluar dari loop bersarang yang dalam sekaligus,
goto
dapat membuat kode lebih ringkas.
Namun, goto
dapat membuat alur kode menjadi kompleks, sehingga tidak disarankan terutama pada program berskala besar. Penggunaan berlebihan dapat menyebabkan “spaghetti code” yang sulit dipelihara. Karena itu, penggunaan goto
sebaiknya mempertimbangkan keterbacaan dan kemudahan pemeliharaan kode.
2. Sejarah dan Kontroversi Pernyataan goto
Pernyataan goto
adalah salah satu struktur kontrol paling awal dalam bahasa pemrograman dan sudah digunakan sebelum bahasa C ada. Namun, penggunaannya telah menjadi subjek perdebatan, khususnya sejak berkembangnya pemrograman terstruktur. Bagian ini menjelaskan sejarah dan kontroversi seputar goto
.
Asal-usul dan Peran Awal goto
Pada masa awal perkembangan pemrograman, goto
merupakan salah satu cara utama untuk memindahkan alur eksekusi ke lokasi lain. Bahasa pemrograman awal belum memiliki struktur kontrol yang canggih seperti sekarang, sehingga goto
sering digunakan untuk membuat loop dan percabangan. Akibatnya, program pada masa itu memiliki alur yang sering melompat-lompat.
Namun, kode dengan banyak lompatan menjadi sulit dipahami dan disebut “spaghetti code”. Untuk mengatasi masalah ini, mulai diperkenalkan struktur kontrol yang lebih jelas seperti if
, for
, dan while
, sehingga penggunaan goto
berkurang.
Pemrograman Terstruktur dan Perdebatan tentang goto
Pada tahun 1970-an, ilmuwan komputer terkenal Edsger Dijkstra menyatakan bahwa goto
merugikan kualitas kode. Makalahnya “Goto Statement Considered Harmful” berpengaruh besar dalam mempopulerkan pemrograman terstruktur, yang menganjurkan penggunaan struktur kontrol yang jelas agar kode mudah dibaca dan dikelola.
Pemrograman terstruktur menekankan penulisan kode dengan alur yang jelas menggunakan loop dan percabangan, sehingga pembuatan program tanpa goto
menjadi hal yang dianjurkan.
Posisi goto
di Era Modern
Saat ini, sebagian besar bahasa pemrograman tidak merekomendasikan goto
, tetapi dalam beberapa kasus masih digunakan. Dalam bahasa C, goto
kadang dianggap tepat untuk skenario tertentu seperti penanganan error. Meski demikian, secara umum dianjurkan untuk menggunakan struktur kontrol lain seperti if
atau while
.
Perdebatan tentang apakah goto
layak digunakan masih ada hingga kini. Namun, dari segi keterbacaan dan pemeliharaan, penggunaannya harus dipertimbangkan secara hati-hati.
3. Kelebihan dan Kekurangan Pernyataan goto
goto
memungkinkan alur kode yang fleksibel yang sulit dicapai dengan struktur kontrol lain, tetapi juga dapat menurunkan keterbacaan dan kemudahan pemeliharaan program. Bagian ini membahas kelebihan dan kekurangan goto
dengan contoh konkret.
Kelebihan goto
- Menyederhanakan penanganan error yang kompleks
Salah satu kelebihangoto
adalah kemampuannya untuk menyederhanakan penanganan error, khususnya ketika terdapat banyak percabangan bersarang. Saat terjadi error, kita dapat melompat ke satu lokasi untuk melepaskan semua sumber daya.
Contoh: Mengelola beberapa sumber daya dan melepaskannya jika terjadi error.
#include <stdio.h>
#include <stdlib.h>
int main() {
FILE *file = fopen("example.txt", "r");
if (!file) {
printf("Gagal membuka file\n");
goto cleanup; // Lompat untuk membersihkan sumber daya
}
char *buffer = (char *)malloc(256);
if (!buffer) {
printf("Gagal mengalokasikan memori\n");
goto cleanup;
}
// Proses lainnya
cleanup:
if (file) fclose(file);
if (buffer) free(buffer);
printf("Pembersihan selesai\n");
return 0;
}
Dengan goto
, kita dapat mengelola pembersihan sumber daya di satu tempat, sehingga mengurangi kompleksitas kondisi bersarang.
- Memudahkan keluar dari loop bersarang
Jika ingin keluar dari loop bersarang secara langsung,goto
dapat menjadi solusi yang sederhana.
Contoh: Keluar dari loop ganda sekaligus.
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
if (i * j > 30) {
goto exit_loop;
}
printf("i=%d, j=%d\n", i, j);
}
}
exit_loop:
printf("Loop selesai\n");
Kekurangan goto
- Menurunkan keterbacaan kode
Lompatan alur menggunakangoto
dapat membuat kode sulit diikuti oleh pengembang lain, khususnya pada proyek besar. - Berpotensi menimbulkan bug
Jika label ditempatkan di posisi yang tidak tepat atau inisialisasi terlewat, alur program dapat menjadi tidak terduga. - Menjadi penyebab “spaghetti code”
Penggunaangoto
secara tidak teratur membuat kode penuh lompatan yang sulit dibaca dan dipelihara.
Ringkasan
goto
dapat bermanfaat pada kondisi tertentu, seperti penanganan error atau keluar dari loop bersarang, tetapi penggunaannya harus dibatasi. Umumnya, disarankan menggunakan struktur kontrol lain yang lebih jelas.

4. Contoh Penggunaan goto
yang Tepat
Sebagai bagian dari struktur kontrol, goto
dapat berguna pada situasi tertentu. Bagian ini membahas dua skenario utama: penanganan error dan keluar dari loop bersarang.
Penggunaan goto
untuk Penanganan Error
Karena bahasa C tidak memiliki mekanisme exception handling seperti try-catch
, goto
sering digunakan untuk mengelola pelepasan sumber daya ketika terjadi error.
Contoh: Mengelola beberapa file dan buffer memori dengan penanganan error terpusat.
#include <stdio.h>
#include <stdlib.h>
int main() {
FILE *file1 = NULL;
FILE *file2 = NULL;
char *buffer = NULL;
file1 = fopen("file1.txt", "r");
if (!file1) {
printf("Tidak dapat membuka file1.txt\n");
goto error;
}
file2 = fopen("file2.txt", "r");
if (!file2) {
printf("Tidak dapat membuka file2.txt\n");
goto error;
}
buffer = (char *)malloc(1024);
if (!buffer) {
printf("Gagal mengalokasikan memori\n");
goto error;
}
printf("Operasi file dan memori selesai tanpa error\n");
free(buffer);
fclose(file2);
fclose(file1);
return 0;
error:
if (buffer) free(buffer);
if (file2) fclose(file2);
if (file1) fclose(file1);
printf("Terjadi error, sumber daya dibersihkan\n");
return -1;
}
Keluar dari Loop Bersarang
Dalam loop bersarang, jika suatu kondisi tertentu tercapai, goto
dapat digunakan untuk keluar dari semua loop sekaligus.
Contoh: Keluar dari loop ganda saat kondisi terpenuhi.
#include <stdio.h>
int main() {
int i, j;
for (i = 0; i < 10; i++) {
for (j = 0; j < 10; j++) {
if (i * j > 30) {
goto exit_loop;
}
printf("i = %d, j = %d\n", i, j);
}
}
exit_loop:
printf("Loop dihentikan karena kondisi terpenuhi\n");
return 0;
}
5. Kasus di Mana goto
Sebaiknya Dihindari dan Alternatifnya
goto
memang berguna pada situasi tertentu, tetapi penggunaan yang berlebihan dapat menurunkan keterbacaan dan kemudahan pemeliharaan kode. Pada program yang kompleks, sulit untuk menelusuri alur lompatan, yang dapat memicu bug. Bagian ini membahas kapan goto
sebaiknya dihindari dan alternatifnya.
Kapan goto
Sebaiknya Dihindari
- Kode yang memprioritaskan keterbacaan
Karenagoto
mengubah alur eksekusi secara tiba-tiba, kode bisa menjadi sulit dipahami, terutama pada proyek besar atau kolaboratif. - Jika penanganan error terstruktur memungkinkan
Di banyak bahasa pemrograman, penanganan error dapat dilakukan tanpagoto
. Bahkan di C, desain yang baik memungkinkan error ditangani dengan fungsi terpisah atau pola kontrol lain. - Pada struktur bersarang yang dalam
Menggunakangoto
di dalam struktur bersarang dapat memperbesar risiko terbentuknya “spaghetti code”. Lebih baik menggunakan variabel penanda (flag) atau logika kontrol lain.
Alternatif goto
1. Menggunakan Variabel Flag
Untuk keluar dari loop bersarang, gunakan variabel flag yang memberi sinyal kapan loop harus dihentikan.
#include <stdio.h>
int main() {
int i, j;
int exit_flag = 0;
for (i = 0; i < 10; i++) {
for (j = 0; j < 10; j++) {
if (i * j > 30) {
exit_flag = 1;
break;
}
printf("i = %d, j = %d\n", i, j);
}
if (exit_flag) break;
}
printf("Loop selesai\n");
return 0;
}
2. Memecah Fungsi untuk Penanganan Error
Alih-alih menggunakan goto
untuk mengelola error, bagi proses menjadi fungsi-fungsi kecil yang mengembalikan kode status, sehingga penanganan error menjadi lebih jelas.
#include <stdio.h>
#include <stdlib.h>
int read_file(FILE **file, const char *filename) {
*file = fopen(filename, "r");
if (!*file) {
printf("Gagal membuka %s\n", filename);
return -1;
}
return 0;
}
int allocate_memory(char **buffer, size_t size) {
*buffer = (char *)malloc(size);
if (!*buffer) {
printf("Gagal mengalokasikan memori\n");
return -1;
}
return 0;
}
int main() {
FILE *file1 = NULL;
char *buffer = NULL;
if (read_file(&file1, "file1.txt") < 0) {
return -1;
}
if (allocate_memory(&buffer, 1024) < 0) {
fclose(file1);
return -1;
}
// Proses lainnya
free(buffer);
fclose(file1);
printf("Proses selesai tanpa error\n");
return 0;
}
3. Memanfaatkan break
atau continue
Pada loop tunggal atau bersarang dangkal, break
atau continue
sering cukup untuk menggantikan goto
.
Ringkasan
goto
sebaiknya menjadi pilihan terakhir. Gunakan alternatif seperti variabel flag, pemecahan fungsi, atau break
/continue
untuk menjaga keterbacaan dan kemudahan pemeliharaan.
6. Praktik Terbaik dalam Menggunakan goto
goto
adalah struktur kontrol yang kuat, tetapi jika disalahgunakan dapat mengurangi kualitas kode. Berikut adalah beberapa praktik terbaik:
1. Gunakan secara minimal
Batasi penggunaan goto
hanya untuk kasus seperti penanganan error dan keluar dari loop bersarang.
2. Gunakan untuk pembersihan sumber daya
FILE *file = fopen("example.txt", "r");
if (!file) {
goto cleanup;
}
char *buffer = (char *)malloc(1024);
if (!buffer) {
goto cleanup;
}
// Proses lainnya
cleanup:
if (buffer) free(buffer);
if (file) fclose(file);
3. Beri nama label yang jelas
Gunakan nama label yang mendeskripsikan tujuan lompatan, seperti cleanup
atau error
.
4. Hindari penggunaan berlebihan
Terlalu banyak goto
akan membuat kode sulit dipahami dan rawan bug.
5. Jangan mencampur dengan struktur kontrol lain secara rumit
Menggabungkan goto
dengan if
, while
, atau for
secara kompleks akan menyulitkan pembacaan alur program.
6. Lakukan code review
Kode yang menggunakan goto
sebaiknya ditinjau ulang oleh pengembang lain untuk memastikan penggunaannya memang diperlukan.
7. Kesimpulan
Artikel ini telah membahas pernyataan goto
dalam bahasa C, mulai dari dasar penggunaannya, sejarah, kelebihan dan kekurangan, contoh penggunaan yang tepat, situasi yang harus dihindari, alternatif, hingga praktik terbaik.
Memahami dan Menggunakan goto
dengan Bijak
goto
bermanfaat dalam skenario tertentu seperti penanganan error dan keluar dari loop bersarang yang dalam, tetapi sebaiknya dihindari jika ada alternatif yang lebih jelas.
Ikuti Praktik Terbaik
Gunakan goto
secara minimal, beri label yang jelas, dan fokuskan penggunaannya untuk pembersihan sumber daya atau alur khusus yang memang sulit digantikan oleh struktur kontrol lain.