Beranda
blog
golang
Merubah response data ke csv dengan golang
Teranix
Oktober 20, 2024

Merubah response data ke csv dengan golang


Dalam dunia pengembangan perangkat lunak, terkadang kita perlu mengonversi data dari satu format ke format lain untuk keperluan analisis atau integrasi dengan sistem lainnya. Salah satunya adalah mengubah response data dari API menjadi format CSV. Pada blog kali ini dibuat dengan bahasa GO. 

1. Membuat Struct

kita perlu memiliki struktur data yang jelas dan terorganisir sebelum mengonversi data ke format CSV. Dalam contoh kode dibawah ini, struct User digunakan untuk merepresentasikan entitas pengguna dengan atribut Nim, Name, dan Campus. Yang nantinya akan di urutkan setiap kolom dengan entitas yang sama ketika berbentuk csv
 type User struct {
   Nim     string
   Name    string
   Campus  string
}

2. Buat Function

Yang perlu dilakukan adalah memasukkan data ke struct secara manual karena ini hanya sebagai contoh simpel tanpa database : 

func CsvUser(w http.ResponseWriter, r *http.Request) {
	data := []User{
		{"12345", "Alice", "Campus A"},
		{"67890", "Bob", "Campus B"},
		{"11223", "Charlie", "Campus C"},
	}
} 

Di golang sendiri sudah terdapat modul encoding bawaan untuk csv. Lalu membuat header table csv kedalam csv.NewWriter() dengan parameter bytes.Buffer yang digunakan sebagai penyimpanan sementara untuk data CSV yang akan buat. Dengan menggunakan buffer, kita dapat menulis data ke dalam memori terlebih dahulu sebelum mengirimkannya sebagai response HTTP.


func CsvUser(w http.ResponseWriter, r *http.Request) {
	data := []User{
		{"12345", "Alice", "Campus A"},
		{"67890", "Bob", "Campus B"},
		{"11223", "Charlie", "Campus C"},
	}

	csvbuffer := bytes.Buffer{}
	writer := csv.NewWriter(&csvbuffer)

	header := []string{"Nim", "Name", "Campus"}
	if err := writer.Write(header); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
}

Diatas kita menyimpan Nim, Name, Campus diawal untuk sebagai header. Jika masih belum paham kode diatas akan membuat header utama pada tabel, lihat gambar dibawah yang background merah.


Selanjutnya, membuat looping dari data ke variabel writer. Sama seperti sebelumnya hanya saja disini kita memasukkan semua data yang ada didalam struct kedalam writer secara berurutan. Dan juga ketika melakukan insert ke lokal variabel didalam looping kita harus menyusun posisi value field sesuai dengan header yang sebelumnya dibuat. Misal header sebelumnya ( Nim, Name, Campus) maka urutan di dalam looping juga harus sama.
  for _, v := range data {
	datacsv := []string{v.Nim, v.Name, v.Campus}
	if err := writer.Write(datacsv); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
    }

Jangan lupa melakukan Flush(). langkah ini memastikan semua data yang ada dalam buffer ditulis sepenuhnya. Ini penting untuk memastikan tidak ada data yang tertinggal di buffer sebelum kita mengirimkan ke user.


  writer.Flush()
if err := writer.Error(); err != nil {
   http.Error(w, err.Error(), http.StatusInternalServerError)
		return
}

w.Header().Set("Content-Type", "text/csv")
w.Header().Set("Content-Disposition", "attachment; filename=datauser.csv")
w.Write(csvbuffer.Bytes()
  • w.Header().Set("Content-Type", "text/csv")

    Baris ini mengatur tipe konten (Content-Type) dari respons HTTP menjadi "text/csv". Ini memberi tahu klien bahwa respons yang dikirimkan akan berisi data dalam format CSV.

  • w.Header().Set("Content-Disposition", "attachment; filename=datauser.csv"

    Di sini, header Content-Disposition diatur. Dengan nilai "attachment; filename=datauser.csv", kita memberitahu browser bahwa respons yang diterima adalah file yang harus diunduh dengan nama "datauser.csv". Ini membuat browser mengonfigurasi perilaku unduhan, seperti menampilkan dialog "Simpan File" dengan nama default "datauser.csv".

  • w.Write(csvbuffer.Bytes())

    Baris ini menulis isi dari buffer CSV ke respons HTTP. Dengan menggunakan csvbuffer.Bytes(), kita mengambil slice byte dari buffer yang berisi data CSV yang telah kita buat sebelumnya. Data ini kemudian ditulis ke respons HTTP, yang akan dikirimkan kepada klien.

3. Kode Lengkap


  package main

import (
	"bytes"
	"encoding/csv"
	"fmt"
	"log"
	"net/http"
)

type User struct {
	Nim    string
	Name   string
	Campus string
}

func CsvUser(w http.ResponseWriter, r *http.Request) {
	data := []User{
		{"12345", "Alice", "Campus A"},
		{"67890", "Bob", "Campus B"},
		{"11223", "Charlie", "Campus C"},
	}

	csvbuffer := bytes.Buffer{}
	writer := csv.NewWriter(&csvbuffer)

	header := []string{"Nim", "Name", "Campus"}
	if err := writer.Write(header); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	for _, v := range data {
		datacsv := []string{v.Nim, v.Name, v.Campus}
		if err := writer.Write(datacsv); err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
	}

	writer.Flush()
	if err := writer.Error(); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	w.Header().Set("Content-Type", "text/csv")
	w.Header().Set("Content-Disposition", "attachment; filename=datauser.csv")
	w.Write(csvbuffer.Bytes())
}

func serverRun(port int) {
	loggprint := `
++++++++++++++++++++++++++++++++++
| Server Running
| Host  : http://localhost:%d/
| Port  : %d
++++++++++++++++++++++++++++++++++

`
	fmt.Printf(loggprint, port, port)
}

func main() {
	http.HandleFunc("/csv", CsvUser)
	port := 8082
	
	serverRun(port)
	log.Fatal(http.ListenAndServe(":8082", nil))
}
  

Penulis blog

Tidak ada komentar