Setup Laravel 5.5 di OS Ubuntu 16.04

*Ini catatan pribadi bukan tutorial, tapi kalo mau nanya-nanya silahkan ke: mhyusufibrahim@gmail.com

Setup Laravel dengan menggunakan Docker containers adalah hal yang umum dilakukan saat ini dalam mengkonfigurasi lingkungan kerja (bahkan production) dalam pengembangan Web karena teknologi-teknologi tersebut hingga saat ini adalah hal yang masih cukup hangat untuk dibicarakan.

Saya akan mencoba belajar dengan tutorial ini dengan beberapa modifikasi.

Sebelum mulai ini detail env di laptop yang saya gunakan (Thinkpad X220)

╰─➤  docker -v; docker-compose -v; lsb_release -a

Docker version 17.12.1-ce, build 7390fc6

docker-compose version 1.17.0, build ac53b73

No LSB modules are available.

Distributor ID: Ubuntu

Description: Ubuntu 16.04.4 LTS

Release: 16.04

Codename: xenial

Bila anda belum punya Docker dan Docker Compose jangan lupa Install dulu.

 

Resolve DNS error dari dalam container

Container dalam host kita terkadang gagal untuk mengontak url-url yang diberikan karena DNS serve yang salah, contoh error adalah sebagai berikut:

╭─yoesoff@yoesoff-ThinkPad-X220 ~/Development 
╰─➤ docker run richarvey/nginx-php-fpm:1.4.1 ping www.google.com
ping: bad address 'www.google.com'

dan poin penting pertama adalah Konfigurasi DNS di Ubuntu yang baru adalah:

sudo vim /etc/docker/daemon.json

# Bukan lagi di: /etc/default/docker

Cara memperbaiki error terkait DNS ini:

  1. Cek DNS yang dipakai host Laptop kita:
  2. Masukan ke /etc/docker/daemon.json
  3. Restart servis Docker
Selection_117.png
seusaikan DNS di sudo vim /etc/docker/daemon.json supaya sama dengan hasil nmcli
 1 { 
 2 "dns": ["203.142.82.224", "182.253.236.236", "192.168.43.1"] 
 3 }

DNS Google, Telkom dan Tri

{
 "dns": ["8.8.8.8", "8.8.4.4", "203.142.82.224", "182.253.236.236", "1.1.1.1", "202.155.0.10", "202.155.0.15", "202.155.0.20", "202.155.0.25", "202.155.30.227", "10.0.18.38", "10.0.18.42"]
}

 

Siapkan DockerFile untuk membuat custom Image PHP7

DockerFile

╭─yoesoff@yoesoff-ThinkPad-X220 ~/Development/DREAMS-DBKL ‹development*›
 ╰─➤ vim Dockerfile
 1 FROM phpdockerio/php72-fpm 
 2 RUN apt-get update -y && apt-get install -y openssl zip unzip git
 3 #RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
 4 #RUN apt-get install pdo mbstring
 5 WORKDIR /app
 6 COPY . /app
 7 RUN composer install
 8
 9 CMD php artisan serve --host=0.0.0.0 --port=8181
 10 EXPOSE 8181

Kenapa Menggunakan phpdockerio/php72-fpm dari phpdocker.io ?

PHPDocker.io – PHP 7.2 / FPM container image

Ubuntu 16.04 PHP 7.2 FPM container image for PHPDocker.io projects. Packages are provided by Ondřej Surý.

Smaller in size than PHP’s official container (170MB vs 501MB) plus you don’t need to install any build dependencies let alone compile anything, Dotdeb already ship binaries for the vast majority, if not all, of PHP extensions available on PHP7.

Selection_094.png
Paling banyak di pull
Selection_095.png
PHP terbaru versi 7.2

 Jadinya saya pakai yang ini:

richarvey/nginx-php-fpm

Build Image

Selection_088.png

Penjelasan:

  1. docker build -t nx-php7-image .
    • Perintah untuk membuat Image berdasarkan konfigurasi DockerFile di currrent project folder.

Bila saat proses build terjadi error sbb: “Err:1 http://archive.ubuntu.com/ubuntu xenial InRelease” ikuti solusi ini. Bila tidak berhasil coba ganti network provider internet anda.

Selection_091.png
Ini adalah Image yang kita buat berdasarkan phpdockerio/php72-fpm

Running Image (Menjalankan Container)

Selection_087.png

Selection_089.png

Penjelasan:

  1. docker run -p 8181:8181 nx-php7-image
    • Menjalankan peruntah run untuk membuat container dari image nx-php7-image
    • bila ingin jalan dibelakang layar sebagai daemon tambahkan -d
      • docker run -d -p 8181:8181 nx-php7-image

Mematikan / Stop Running Container

Selection_086.png
Container yang sedang berjalan tidak bisa di stop dengan ctrl+c

Penjelasan:

  1. $ docker ps
    • Melihat active container dan mendapatkan ID nya, disini IDnya adalah: e37794a1c2e8
  2. $ docker container stop e37794a1c2e8
    • Mematikan container yang sedang berjalan
    • Ada banyak containers yang perlu dimatikan semua ?
      • docker kill $(docker ps -q)

Sampai disini kita mempelajari

  1. Mengenal DockerFile dan Syntaxnya.
  2. Membuild Image dari Image yang telah ada.
  3. Merunning container dari Image yang telah di build.
  4. Melihat available images dengan docker images
  5. Melihat running containers dengan docker ps
  6. Mematikan running container dengan  docker container stop ID-CONTAINER

abraham-lincoln-9382540-2-402

“Container(s) Adalah instance dari sebuah Image” 

– Abraham Lincoln 1809

Bonus stage, akses masuk ke dalam Container

╭─yoesoff@yoesoff-ThinkPad-X220 ~/Development 
╰─➤ docker exec -it <mycontainer> bash

Selection_093.png

Menyiapkan Image Oracle 12c

logo-oracle12

Kenapa pakai Image dari sath89/oracle-12c ?

Oracle Standard Edition 12c Release 1



Oracle Standard Edition 12c Release 1 on Ubuntu
This Dockerfile is a trusted build of Docker Registry.

Persiapan dan instalasi

Sumber referensi asal: https://github.com/MaksymBilenko/docker-oracle-12c

Pull image sath89/oracle-12c

Selection_098.png
docker pull sath89/oracle-12c

nobita

“Docker pull adalah proses mengambil image atau a repository dari sebuah registry”

– Nobita 2099

Jalankan Containers di Background

Selection_099.png

docker run -d -p 8080:8080 -p 1521:1521 sath89/oracle-12c

List of Running Containers

Selection_100.png
docker ps

Instalasi SQLPLUS (Sejenis dengan psql milik PostgreSQL)

Artikel yang mengulas SQLPLUS lebih dalam berbahasa Indonesia baca disini.

Selection_101.png
Uppsss! mari install dulu

SQL*Plus Overview

SQL*Plus is an interactive and batch query tool that is installed with every Oracle Database installation. It has a command-line user interface, a Windows Graphical User Interface (GUI) and the iSQL*Plus web-based user interface.

There is also the SQL*Plus Instant Client which is a stand-alone command-line interface available on platforms that support the OCI Instant Client. SQL*Plus Instant Client connects to any available Oracle database, but does not require its own Oracle database installation. See the Oracle Call Interface Programmer’s Guide for more information on the OCI Instant Client.

Download RPMs files di http://www.oracle.com/technetwork/topics/linuxx86-64soft-092277.htmlSelection_102.png

Ikuti cara ini untuk install di Ubuntu atau ini yang lebih jelas.

╭─yoesoff@yoesoff-ThinkPad-X220 ~/Downloads  

╰─➤  sudo alien -i oracle-instantclient12.2-basic-12.2.0.1.0-1.x86_64.rpm 

dpkg --no-force-overwrite -i oracle-instantclient12.2-basic_12.2.0.1.0-2_amd64.debSelecting previously unselected package oracle-instantclient12.2-basic.(Reading database ... 293364 files and directories currently installed.)Preparing to unpack oracle-instantclient12.2-basic_12.2.0.1.0-2_amd64.deb ...Unpacking oracle-instantclient12.2-basic (12.2.0.1.0-2) ...Setting up oracle-instantclient12.2-basic (12.2.0.1.0-2) ...Processing triggers for libc-bin (2.23-0ubuntu10) ...

╭─yoesoff@yoesoff-ThinkPad-X220 ~/Downloads  

╰─➤  sudo alien -i oracle-instantclient12.2-devel-12.2.0.1.0-1.x86_64.rpm  

dpkg --no-force-overwrite -i oracle-instantclient12.2-devel_12.2.0.1.0-2_amd64.debSelecting previously unselected package oracle-instantclient12.2-devel.(Reading database ... 293386 files and directories currently installed.)Preparing to unpack oracle-instantclient12.2-devel_12.2.0.1.0-2_amd64.deb ...Unpacking oracle-instantclient12.2-devel (12.2.0.1.0-2) ...Setting up oracle-instantclient12.2-devel (12.2.0.1.0-2) ...

╭─yoesoff@yoesoff-ThinkPad-X220 ~/Downloads  

╰─➤  sudo alien -i oracle-instantclient12.2-sqlplus-12.2.0.1.0-1.x86_64.rpm  

dpkg --no-force-overwrite -i oracle-instantclient12.2-sqlplus_12.2.0.1.0-2_amd64.debSelecting previously unselected package oracle-instantclient12.2-sqlplus.(Reading database ... 293441 files and directories currently installed.)Preparing to unpack oracle-instantclient12.2-sqlplus_12.2.0.1.0-2_amd64.deb ...Unpacking oracle-instantclient12.2-sqlplus (12.2.0.1.0-2) ...Setting up oracle-instantclient12.2-sqlplus (12.2.0.1.0-2) ...

Konfigurasi hingga akhrinya sqlplus64 jalan

Selection_103.png
sudo ldconfig &&  . ~/.zshrc

Login ke database dengan SQLPLUS

Selection_104.png
system/oracle@//localhost:1521/xe

Instal Oracle SQL Developer

Nah, kalau SQLPLUS adalg versi console di terminal maka Oracle SQL Developer adalah versi desktopnya.

Download Oracle SQL Developer disini.

Pilih yang RPM supaya bisa di insall dengan menggunakan Alien.

Linux RPM

(4e0156dd0edf4ecfc8d65c989ebf548a)
Installation NotesJDK 8 or above require

Perintah instalasi Oracle Developer Studio

sudo alien -i --scripts sqldeveloper-17.4.1.054.0712-1.noarch.rpm

Selection_105.png

Hasil instalasi

Selection_106.png

Selection_107.png

Setting Koneksi ke database yang berada didalam kontainer

hostname: localhost
port: 1521
sid: xe
service name: xe
username: system
password: oracle
Selection_108.png

Koneksi dari Oracle SQL Developer ke Oracle DB 12c yang berada di Container

Sampai disini kita mempelajari hal lain yaitu:

  1. Pull image dan menjalankan container Oracle DB 12c.
  2. Menginstal dan login ke SQLPLUS di console terminal.
  3. Mengistall GUI Buat Oracle 12c yaitu Oracle SQL Developer

Jadi Sampai disini kita sudah memiliki beberapa hal penting:

  1. Container yang berisi PHP7 (Dengan custom Image)
  2. Container yang berisi Oracle 12c
  3. SQLPLUS Oracle SQL Developer

Selanjutnya mari setup docker compose…!

 

Docker Compose

spongebob-squarepants
“Compose is a tool for defining and running multi-container Docker applications. ” Spongebob

Docker Compose

Compose is a tool for defining and running multi-container Docker applications. With Compose, you use a Compose file to configure your application’s services. Then, using a single command, you create and start all the services from your configuration.

Mau tau lebih banyak tentang docker-compose ? baca aja ini dan ini.

Mari kita mulai dengan memastikan Docker Compose itu sendiri sudah ada di Laptop atau PC kita:

╭─yoesoff@yoesoff-ThinkPad-X220 ~/Development/TestAja ‹development*› 
╰─➤ docker-compose -v
docker-compose version 1.17.0, build ac53b73

Masuk Ke Project Folder

Selection_110.png
Lihat, error diatas menyuruh kita menyiapkan file docker-compose.yml

Membuat file docker-compose.yml (Sejajar folder app)

Selection_111.png
Image yang dipakai nx-php7 (Build ulang aja yang sebelumnya nx-php7-image jadi nx-php7)
Selection_112.png
docker-compose up (matikan: docker-compose stop)

Dockerfile

╭─yoesoff@yoesoff-ThinkPad-X220 ~/Development/DREAMS-DBKL ‹development*› 
╰─➤ ccat Dockerfile 
FROM phpdockerio/php72-fpm

# https://medium.com/@shakyShane/laravel-docker-part-2-preparing-for-production-9c6a024e9797 
COPY . /var/www
WORKDIR /var/www

# Do not execute composer as root
# RUN useradd -ms /bin/bash phpguy
# set phpguy as sudoer
# RUN adduser phpguy sudo
# switch current user
# USER phpguy
# *Docker root is not Host's root, so it's ok to root inside container CMIIW
# RUN composer install

# better way to run composer: https://stackoverflow.com/questions/46786589/running-composer-install-within-a-dockerfile
CMD bash -c "composer install && php artisan serve --host=0.0.0.0 --port=8181"
#CMD bash -c "composer install"

EXPOSE 80

 

Docker Compose File

╭─yoesoff@yoesoff-ThinkPad-X220 ~/Development/DREAMS-DBKL ‹development*› 
╰─➤ ccat docker-compose.yml 
version: '3.2'
services:
 database:
 image: sath89/oracle-12c
 ports: 
   - "1521:1521" 
   - "8080:8080" 
 restart: always

dream_dbkl:
 depends_on:
 - database
 build: 
 context: .
 dockerfile: ./Dockerfile
 ports:
 - "8181:8181"
 restart: always
 environment:
 DATABASE_PORT: "1521"
 DATABASE_SID: xe
 DATABASE_SERVICE_NAME: xe
 DATABASE_USERNAME: system 
 DATABASE_PASSWORD: oracle
 DATABASE_NAME: dreams

Selanjutnya

docker-compose build # up juga include build kalo belum
# Lalu
docker-compose up
# lalu 
docker run sath89/oracle-12c /entrypoint.sh

 

 

Bila ada errors saat docker-compose build hapus caches:

$ docker-compose rm

Containers dengan Docker Compose

Selection_126.png

 

Bonus Stage

Cara Stop dan Menghapus semua containers

  1. Melihat semua containers yang ada: docker ps -s
  2. Melihat containers yang aktif: docker ps
  3. Stop semua containers:  docker stop $(docker ps -a -q)
  4. Remove semua containers:  docker rm $(docker ps -a -q)
  5. 3 dan 4 hanya mau eksekusi yang running saja ? remove -a
Selection_115.png
Container hanya di stop
Selection_116.png
Containers di remove

Dari berbagai sumber

https://buddy.works/guides/laravel-in-docker

View story at Medium.com

https://hub.docker.com/r/phpdockerio/php72-fpm/~/dockerfile/

https://hub.docker.com/r/sath89/oracle-12c/

https://codediary.net/posts/install-sqlplus-on-ubuntu-16-04/

https://askubuntu.com/questions/159939/how-to-install-sqlplus

https://stackoverflow.com/questions/41928566/installing-oracle-datamodeler-on-ubuntu-16-04/43524386

https://linuxhint.com/docker-compose-tutorial/

https://askubuntu.com/questions/170640/how-to-disable-apache2-server-from-auto-starting-on-boot (disable host running service)

Troubleshoting

https://github.com/gliderlabs/docker-alpine/issues/183

https://odino.org/cannot-connect-to-the-internet-from-your-docker-containers/

https://unix.stackexchange.com/questions/28941/what-dns-servers-am-i-using Check my DNS

https://askubuntu.com/questions/475764/docker-io-dns-doesnt-work-its-trying-to-use-8-8-8-8 Resolved my DNS error

 

 

 

 

Advertisements

Catatan Membuat Guestbook dengan Laravel 5.5 dan VueJS

Ini hanya catatan personal bukan tutorial!

Pada postingan ini saya membuat catatan untuk memudahkan kembali saya mengingat-ingat apa yang telah saya lakukan dan saya pelajari. Kali ini saya mencoba mempelajari Laravel 5.5 LTS dengan VueJS (Laravel+Vue saya lihat sebagai sebuah pasangan serasi untuk web development modern saat ini).

Catatan ini sendiri tidak akan ada banyak tulisan karena proses instalasi  Laravel dan VueJS sendiri berada di artikel lain yang terpisah yaitu Larastart yang sebelumnya telah saya buat (Artikel catatan tentang Larastart ini cukup panjang dan tidak begitu rapih).

Mari kita mulai mencatat dengan snapshot:

Tahap 1. Generate Model dan Migration

3.Generate-Model-dan-Migration
php artisan make:model Guestbook/Signature -m

Ketika menyertakan -m  mala akan memberikan tanda pada command untuk juga menggenerate migration untuk kita, hal ini membantu kita menghemat banyak waktu.

Edit dan sesuaikan App\Guestbook\Signature.php dan database/migrations/2018_03_03_032608_create_signatures_table.php (cek di github project ini).

Tahap 2. Generate Model Factory

4.Factory.png
php artisan make:factory SignatureFactory

Setelah Factory digenerate gunakan Faker untuk memproduksi data Dummy/Fake yang akan kita gunakan selama testing.

5.faker
database/factories/SignatureFactory.php

Membuat seeder supaya dummy data bisa digenerate saat provisioning Vagrant / Docker.

6.seeder-generate.png

Tahap 3. Generate Controllers

Generate 2 Files Controllers sebagai berikut:

  1. php artisan make:controller Api/V1/Guestbook/SignatureController
  2. php artisan make:controller Api/V1/Guestbook/ReportSignature

7.set-COntrollers.png

8.generated-controller

Tahap 4. Generate Transformer

8.Resource-Signature-transformer.png

Tahap 5. Siapkan Halaman Utama

Generate Controller untuk view

╭─yusuf@yusuf-he ~/htdocs/Larastarter ‹master*›
╰─➤ ./artisan make:controller Guestbook/SignatureController
Controller created successfully.

10.controoler-view

Create HTML view

11.guest-book-index.png

13.routes-only

 

Sumber: Link

Catatan belajar Framework frontend JS Vue

Free $20 Linode Cloud hosting Coupon, register at  Free Linode Cloud Hosting

(Coupon $20 available at Linode $.20 Coupon ) 👍🏿

Post ini dimaksudkan sebagai catatan pribadi saya dalam belajar Vue.js, saya catat disini karena saya pelupa dan kadang baru ingat setelah Google justru mengarahkan saya ke Blog saya sendiri saat saya mencari sesuatu, kadang baru ngeuh “oh iya saya pernah belajar ini dulu”.

Untuk catatan lain yang tidak menggunakan build tool buka disini: link

Instalasi (link)

1.Install-cli
npm install –global vue-cli
2.test-vue-cli
vue
3.webpack-init1
vue init webpack my-project
3.webpack-init2
Lanjutan vue init webpack my-project
4.get-in
Hasil dari: vue init webpack my-project
5.NPM-Install
npm install
6.NPM-run
npm run dev
7.The-Website
localhost

 

Setup VIM

8.vim-vue-support1
vim .vimrc
8.vim-vue-support2
au BufReadPost *.vue set syntax=html

Create Simple Hello World

11-Hello-files12.HelloWorlds12.HelloWorldsMainJS13.REsult

Create Simple Component

 

16.Instance-with-component-index2
Browser Output

Event Method pada Component

17.methods-pada-components
Event pada vue component

Data Variables dalam Component

18.compoinent-data
Most of the options that can be passed into the Vue constructor can be used in a component, with one special case: data must be a function.

Computed Variable

17.var-computed

Instead of a computed property, we can define the same function as a method instead. For the end result, the two approaches are indeed exactly the same. However, the difference is that computed properties are cached based on their dependencies. A computed property will only re-evaluate when some of its dependencies have changed.

Variable Watcher dalam Component

19.compoinent-watcher
Setiap ada perubahan terdeteksi counter akan bertambah

Style Binding / Kondisi pada Pemberian Class

20.style-binding1
active dan text-danger muncul dari kondisi variable setelahnya
 Cara lain yang lebih pendek (output sama dengan diatas)
Opsi lain

21.style-binding3

Pada componen

<hellow v-bind:pesan=”pesan” v-bind:class=”classObject”></hellow>

Hasilnya komponen pembungkus template akan seperti ini

<span class=”active text-danger”> . . .

Condition

  1. v-if
  2. v-else

Loop

  1. v-for array objects
  2. v-for pada fields
  3. v-for dengan index, key dan value

Miscellenous

  1. Filter data
  2. Add new data record
  3. Delete record from data
  4. Sample ToDo
  5. Property “is” dan “href” pada component
  6. Property “is” dan “src” pada component image
  7. Methods and computed

Form Input

  1. Text input
  2. Checkbox input
  3. Radio Picker
  4. Select input
  5. Multiple Select
  6. Select rendered options
  7. Selected rendered options set value

Components

  1. Component for, Bind dan Is
  2. Pass text sebagai html property
  3. Component props camelCase
  4. Bind input text value ke component
  5. Trigger event dengan $emit
  6. Template component membaca data dalam component
  7. Template dengan text/x-template
  8. v-once untuk cache static content

Transition effects

  1. Transition dan Callback
  2. Postponed

Mixin

  1. Simple sample
  2. Mixins Methods
  3. Global Mixins

Custom Directive

Vue.directive

  1. Simple sample, set-focus directive
  2. Directive callbacks/Hook Function
  3. Hook Arguments
  4. Passing Object 

Render Function

  1. Basic Component
  2. x-template
  3. render template and v-for

Installing and Unistalling SpaceVim / SpaceVim on UBuntu Linux (Or just Linux in General)

I just Installed /SpaceVim on my Ubuntu 14.04 Laptop but I realized that It was wrong because my VIM IDE turned to unfamiliar IDE for me, and the worse case was my previous setting and configurations in my .vimrc are no longer working.

Here is the SpaceVim installation step:

curl -sLf https://spacevim.org/install.sh | bash

spacevim

Installation result (Open the VIM first), beautiful but I think it’s better to use it later…

spacevim100

And here is how to uninstall / remove  SpaceVim from your LInux Computer:

curl -sLf https://spacevim.org/install.sh | bash -s — uninstall

remove-spaceVIM

Finally I get my standard VIM back…

myvim1.png

Google App Engine: Setting up GAE Local Development Server

In this blog post I’m going to show you about install and setting up Google Cloud SDK in Local computer environment for Go / Golang web development, my current computer runs Ubuntu 14.04 as primary os but I’m quite sure that the following steps run on the latest Ubuntu as well.

Requirements :

  1. Ubuntu 14.04 or later
  2. Python 2.7.x or later
  3. Java 1.7 or later
  4. Git

Let’s start the journey :

Download Google Cloud SDK
Download Google Cloud SDK
Extract Google Cloud SDK to local folder
Extract Google Cloud SDK to local folder
Install Google Cloud SDK to local system
Install Google Cloud SDK to local system
Choose yes to improve Google Cloud SDK
Choose yes to improve Google Cloud SDK
Update environment variables / bashrc path
Update environment variables / bashrc path
Update environment variables / bashrc path
Update environment variables / bashrc path
Restart / Reload Bash
Restart / Reload Bash
GCLOUD Init and Login
GCLOUD Init and Login
GCLOUD Init and Login to browser
GCLOUD Init and Login to browser
GCLOUD Init and Login to browser
GCLOUD Init and Login to browser
GCLOUD Init and Login to browser
GCLOUD Init and Login to browser
Give Permission
Give Permission
Give Permission
Give Permission

22.WebLoggedIn

Terminal Logged in
Terminal Logged in
Select Project
Select Project
Check Development App Server
Check Development App Server
Generate ssh Public Key
Generate ssh Public Key
SSH Public Key
SSH Public Key
GitLab Settting
Gitlab Setting
GitLab Settting
GitLab Settting
GitLab SSH Pub key
GitLab SSH Pub key
Install GIT
Install GIT
Clone Code From Repository
Clone Code From Repository
Run development server
Run development server
Runs application
Runs application
Local Web Application
Local Web Application
Admin Server
Admin Server

Golang: Undertanding Basic of Concurrence Programming in the easiest way

In this blog post I’m gonna show you an easy example regarding basic concurrency in Golang programming, it will be an easy step-by-step approach to avoid misapprehend to the example (sample).

What is concurrency?

Concurrency is the composition of independently executing computations.

Concurrency is a way to structure software, particularly as a way to write clean code that interacts well with the real world.

It is not parallelism.

Rob Pike, Google

https://talks.golang.org/2012/concurrency.slide#6

Step 1:

package main

import (
	"fmt"
	"time"
)

func sayHello() {
	for x := 0; x &lt; 10; x++ {
		fmt.Println("Hello ", x)
	}
}

func main() {
	start := time.Now()
	fmt.Println("Start at: ", start)
	fmt.Println("------------------------------------------------------")

	go sayHello()

	fmt.Println("------------------------------------------------------")
	fmt.Println("End at: ", time.Now())
	fmt.Println("Done at: ", time.Now().Sub(start))
}

Output:

basic1

In this  step we do not have output to be printed on the screen from sayHello() because the main process ends before the goroutine being executed. Golang program execution begins by initializing the main package and then invoking the function main. When the function main returns, the program exits. It does not wait for other (non-main) goroutines to complete.

A goroutine is a lightweight thread managed by the Go runtime.

Step 2

func main() {
	start := time.Now()
	fmt.Println("Start at: ", start)
	fmt.Println("------------------------------------------------------")

	go sayHello()

	time.Sleep(time.Second)

	fmt.Println("------------------------------------------------------")
	fmt.Println("End at: ", time.Now())
	fmt.Println("Done at: ", time.Now().Sub(start))
}

Output:

Basic2delay

The example above uses delay to make main function (process) waits the goroutine through 1 second before ends, 1 second is more than enough for Golang to print out all the lines on the screen. for the next step I’m gonna add  delay to the loop inside the sayHello() function so it will takes 9 seconds to be finished (and keep 1 second delay in the main function), let’s see what will take place.

Step 3

func sayHello() {
	for x := 0; x &lt; 10; x++ {
		fmt.Println("Hello ", x)
		time.Sleep(time.Second)
	}
}

func main() {
	start := time.Now()
	fmt.Println("Start at: ", start)
	fmt.Println("------------------------------------------------------")

	go sayHello()

	time.Sleep(time.Second)

	fmt.Println("------------------------------------------------------")
	fmt.Println("End at: ", time.Now())
	fmt.Println("Done at: ", time.Now().Sub(start))
}

Output:

Basic3

Each loop waits for 1 second after printed the text, so in 1 minute it adequate to print 2 lines.

Step 4 Make main function wait goroutine to be done before it ends

We can make main function to wait all goroutines to be done before end it’s process without using primitive delay (time.Sleep(time.Second)) function.

package main

import (
	"fmt"
	"time"
	"sync"
)

func sayHello(wg *sync.WaitGroup) {
	for x := 0; x &lt; 10; x++ {
		fmt.Println("Hello ", x)
		time.Sleep(time.Second)

		if x == 8 {
			wg.Done()
		}

	}
}

func main() {
	var wg sync.WaitGroup

	start := time.Now()
	fmt.Println("Start at: ", start)
	fmt.Println("------------------------------------------------------")

	wg.Add(1)
	go sayHello(&wg)

	wg.Wait()

	fmt.Println("------------------------------------------------------")
	fmt.Println("End at: ", time.Now())
	fmt.Println("Done at: ", time.Now().Sub(start))
}

Output:

basic5

Please pay attention to these lines:

var wg sync.WaitGroup
wg.Add(1) // Should be called before goroutine call
wg.Done()
wg.Wait()

Step 5 Go channel

Channels are the pipes that connect concurrent goroutines. You can send values into channels from one goroutine (ch<-) and receive those values into another goroutine (<-ch).

I don’t want to talk much about channel to avoid confusion, instead I will just show you several behavior of channel.

Receive operation <-ch in the main

package main

import (
	"fmt"
)

func sayHello(msg chan string) {

	msg <- "Hello Lorem ipsum1!"
	msg <- "Hello Lorem ipsum2!"
	msg <- "Hello Lorem ipsum3!"
	close(msg)
}

func main() {
	msg := make(chan string)

	go sayHello(msg)

	for value := range(msg) {
		fmt.Println(value);
	}

	// Or you could just uncomment following lines (but comments 'for' lines first)
	// fmt.Println("1:", <-msg)
	// fmt.Println("2:", <-msg)
	// fmt.Println("3:", <-msg)
	// fmt.Println("4:", <-msg) // empty or error if you did't close(msg)
}

Output:

channelx1

package main

import (
      "fmt"
)

func sayHello(msg chan string) {
      says := "Says: "
      for x := 0; x < 10; x++ {
          says += fmt.Sprintf("Hello-%d ,", x)
          fmt.Println("ok")
      }   

      msg <- says
}

func main() {
      msg := make(chan string)
      go sayHello(msg)
      fmt.Println(<-msg)
}

Output:

channel1

Receive operation (<-msg) in main() is a blocking operation, so the program won’t continue until a value is available.

Receive operation <-ch from goroutine to be printed by function

package main

import (
	"fmt"
)

func sayHello(msg chan string) {

	msg <- "hello world"

}

func printHello2(msg string) {
	fmt.Println(msg)

}

func main() {

	msg := make(chan string)

	go sayHello(msg)

	printHello2(<-msg)

}

Output:

exited1

Select

package main

import (
	"fmt"
	"time"
)

func main() {

	// For our example we'll select across two channels.
	c1 := make(chan string)
	c2 := make(chan string)

	go func() {
		time.Sleep(time.Second * 1)
		c1 <- "one"
	}()

	go func() {
		time.Sleep(time.Second * 2)
		c2 <- "two"
	}()

	for {

		select {
		case msg1, ok := <-c1:
			if ok {
				fmt.Println("received", msg1)
			}
		case msg2, ok := <-c2:
			if ok {
				fmt.Println("received", msg2)
			}
		case <-time.After(3000 * time.Millisecond):
			fmt.Printf("Timed out!")
			return
		}

	}
}

Output:

timeout

The select statement lets a goroutine wait on multiple communication operations.

A select blocks until one of its cases can run, then it executes that case. It chooses one at random if multiple are ready.

Golang: Debuging Go code

In this post I will show you some easy (tricky) ways to debug go code (forget about gdb, it’s too hard to understand).

Print Struct as string

package main

import (
    "fmt"
)

type Person struct {
    Name, Address       string
    Age, Height, Weight int
}

func main() {
    Yusuf := Person{
        Name:    "Yoesoff",
        Address: "Bandung Barat",
        Age:     17,
        Height:  165,
        Weight:  70,
    }   

    fmt.Println(Yusuf) // Print struct as string
}

Output:

{Yoesoff Bandung Barat 17 165 70}
{Yoesoff Bandung Barat 17 165 70}

Use fmt.Printf to find Variable / Object type in Golang

fmt.Printf("%T\n",v)
package main

import (
    "fmt"
)

type Person struct {
    Name, Address       string
    Age, Height, Weight int
}

func main() {
    Yusuf := Person{
        Name:    "Yoesoff",
        Address: "Bandung Barat",
        Age:     17,
        Height:  165,
        Weight:  70,
    }   

     fmt.Printf("%T\n", A)
     fmt.Printf("%T\n", B)
     fmt.Printf("%T\n", Yusuf)
}

Output:

string
int
main.Person

Use reflect to find Variable / Object type in Golang

package main

import (
	"fmt"
	"reflect"
)

type Person struct {
	Name, Address       string
	Age, Height, Weight int
}

func main() {
	Yusuf := Person{
		Name:    "Yoesoff",
		Address: "Bandung Barat",
		Age:     17,
		Height:  165,
		Weight:  70,
	}

	Yuka := &Person{
		"Zha",
		"Bandung Barat",
		16,
		165,
		60,
	}

	A := 10
	B := 12
	C := A + B
	D := "I AM A BATMAN"

	fmt.Println(reflect.TypeOf(Yusuf))
	fmt.Println(reflect.TypeOf(Yuka))
	fmt.Println(reflect.TypeOf(*Yuka))
	fmt.Println(reflect.TypeOf(C))
	fmt.Println(reflect.TypeOf(D))
}

Output:

main.Person
*main.Person
main.Person
int
string

Using go-spew to debug Go data structures (Object and Variable)

Installation

$ go get -u github.com/davecgh/go-spew/spew

  package main

  import (
      "github.com/davecgh/go-spew/spew"
  )

  type Person struct {
      Name, Address       string
      Age, Height, Weight int
  }

  func main() {
      Yusuf := Person{
          Name:    "Yoesoff",
          Address: "Bandung Barat",
          Age:     17,
          Height:  165,
          Weight:  70,
      }

      A := 10
      B := 12
      C := A + B
      D := "Wakwau Golang si Golang"

      spew.Dump(Yusuf)
      spew.Dump(C)
      spew.Dump(D)
  }

Output:

(main.Person) {
Name: (string) (len=7) “Yoesoff”,
Address: (string) (len=13) “Bandung Barat”,
Age: (int) 17,
Height: (int) 165,
Weight: (int) 70
}
(int) 22

(string) (len=23) “Wakwau Golang si Golang”

Using godebug A cross-platform debugger for Go.

Installation:

$ go get github.com/mailgun/godebug

1. install-godebug

Setup Go executable binary path :

2. Setup Go Binari

3. Go-Debug-Running

Insert a breakpoint anywhere in a source file you want to debug:

_ = "breakpoint"

package main

  import "fmt"

  type Person struct {
      Name, Address       string
      Age, Height, Weight int
  }

  func main() {
      Yusuf := Person{
          Name:    "Yoesoff",
          Address: "Bandung Barat",
          Age:     17,
          Height:  165,
          Weight:  70,
      }

      _ = "breakpoint"

      A := 10
      B := 12
      C := A + B
      D := "Wakwau Golang si Golang"
      _ = "breakpoint"

      fmt.Println(A)
      fmt.Println(B)
      fmt.Println(C)
      fmt.Println(D)
      fmt.Println(Yusuf)
  }

Output:

6.Godebugx

Task Scheduling using Laravel 5

In this blog post I will show you an easy example about how to create a simple Laravel 5 Command-Line program to be executed regularly by particular time interval or specified time.

Laravel’s command scheduler allows you to fluently and expressively define your command schedule within Laravel itself. When using the scheduler, only a single Cron entry is needed on your server. Your task schedule is defined in the app/Console/Kernel.php file’s schedule method. To help you get started, a simple example is defined within the method.

Create Simple Laravel Command-Line

we will use two log files to store output text (I show you my real path to avoid confuse ) :

Cron log file :  /home/yusuf/general.log

Scheduler output file: /home/yusuf/htdocs/blog/storage/logs/scheduler.log

 

  • Create app/Console/Commands/SayHello.php.

    1. CreateSayHelloDotPHP
    Create a new PHP file
  • Let’s write the simple short php code

    vim app/Console/Commands/SayHello.php

    namespace App\Console\Commands;
    
      use Illuminate\Console\Command;
    
      class SayHello extends Command
      {
          protected $signature = 'sayhello';
          protected $description = 'Say Hello User';
    
          public function __construct()
          {
              parent::__construct();
          }
    
          public function handle()
          {
              $this->info('Hello user...! ('. date("Y-m-d H:i:s") .') ');
          }
      }
    

    vim app/Console/Commands/Kernel.php

     /**
     * The Artisan commands provided by your application.
     *
     * @var array
     */
     protected $commands = [
         Commands\SayHello::class
     ];
    
  • Check out the new registered Laravel 5 Command-Line in the command list

    3. checkNewCommand
    New registered Laravel Command-line
  • Execute SayHello as Laravel 5 Command-Line program

    4. ExecuteIt
    Execute command line on terminal

Create Scheduler to Execute Command-Line

The next important step is about how to execute our Laravel Command-Line regularly. By using the Laravel scheduler you only need to add the following short line Cron entry to your server an then Laravel Forge will manage the Cron entries for you:

  • Create a log file for our Laravel scheduler storage/logs/scheduler.log:5. Laravel-Logs
  • Edit app/Console/Commands/Kernel.php   

    vim app/Console/Commands/Kernel.php

  • /**
     * Define the application's command schedule.
     *
     * @param \Illuminate\Console\Scheduling\Schedule $schedule
     * @return void
     */
     protected function schedule(Schedule $schedule)
     {
         $filePath = '/home/yusuf/htdocs/blog/storage/logs/scheduler.log';
         $schedule->command('sayhello')->everyMinute()->sendOutputTo($filePath);
     }
    
  • Test execute the scheduler

    ./artisan schedule:run6.scheduler-registered

  • Register schedule command as cron entry

    $ crontab -e7.registerCronEntry.png

     

    CronTabBlog1

  • Save the file and quit text editor
  • Tail the log file to see the result

    tail -f ~/general.log

    tail -f /home/yusuf/htdocs/blog/storage/logs/scheduler.log

    CrontabOutput2

  • That’s all

Golang: Simple Golang Web Application

In this post I’d like to show you a simple web application developed using Go / Golang that demonstrate you several basic web  functionalities such as http request and http response.

The result should be something like this that runs in your web browser:

golang-x1golang-x2

main.go

package main

  import (
      "fmt"
      "html/template"
      "net/http"
      "os"
  )

  type FormData struct {
      Name    string
      Country string
  }

  func form(w http.ResponseWriter, r *http.Request) {
      folderpath, _ := os.Getwd() // Get current folder location
      form, _ := template.ParseFiles(folderpath + "/form.gtpl")
      form.Execute(w, nil)
  }

  func view(w http.ResponseWriter, r *http.Request) {
      if r.Method == "POST" {

          // Process form data
          r.ParseForm()
          name := r.Form["name"][0] // Yes, Go able to receive more than one name
          country := r.Form["country"][0]
          //fmt.Println(name)
          //fmt.Println(country)

          data := FormData{
              Name:    name,
              Country: country,
          }   

          folderpath, _ := os.Getwd() // Get current folder location
          view, _ := template.ParseFiles(folderpath + "/view.gtpl")
          view.Execute(w, data)
      } else {
         fmt.Fprintf(w, "Method not allowed!") // write data to response
      }
  }

  func main() {
      // Routes
      http.HandleFunc("/", form)
      http.HandleFunc("/view", view)

      http.ListenAndServe(":8000", nil) // setting listening port
  }

form.gtpl

<html>

      <body>
<h1>Hallo World</h1>
<form method="POST" action="/view">
              Name : <input name="name" />
              Coutry : <input name="country" />

              <input type="submit" />
          </form>

      </body>

  </html>

view.gtpl

 <html>
  <head>
  <title></title>
  </head>
      <body>
          Hello World 

          Welcome -{{.Name}}- from -{{.Country}}-
      </body>
  </html>

Build and Run The code

golang x3

Code Snapshot

VIMX1VIMX2VIMX3

Golang: Catatan belajar OOP dengan GO language

Source code di sini

Struct pada Golang adalah kumpulan dari fields dan atau properties. Struct berbeda dengan Class pada Java misalnya, karena salah satunya Struct pada Go menggunakan Composition bukan inheritance yaitu dengan meng-compose sebuah struct di struct lainnya sehingga fields dan atau properties dari sebuat struct ada di dalam struct lain yang meng-embed struct tersebut.

Composition atau juga bisa di sebut embedding bisa dikatakan sebagai pengganti penggunaan inheritance di GO ,  untuk menjadikan gambaran yang lebih jelas saya mencoba mempraktekan perilaku tersebut dalam beberapa baris bahasa GO di bawah ini, selain Composition/embedding disini juga terdapat penggunaan interface sederhana, berikut kodenya:


package main

import (
	f "fmt"
	s "strconv"
)

// 1. Manusia pada umumnya
type Manusia struct {
	nama                     string
	umur                     int
	telepon, hanphone, email string
}

// 2. Manusia berstatus Mahasiswa
type Mahasiswa struct {
	Manusia       // Embed Manusia / semacam extend di OOP Java
	kampus, kosan string
	uang_jajan    float32
}

// 3. Mahasiswa berstatus Karyawan
type Karyawan struct {
	Manusia            // Embed Manusia / semacam extend di OOP Java
	perusahaan, asrama string
	salary             float32
}

// Semua manusia pasti makan
func (m Manusia) makan(makanan string) {
	f.Printf("Makan: %s \n", makanan)
}

// Semua manusia pasti minum
func (m Manusia) minum(minuman string) {
	f.Printf("Minum: %s \n", minuman)
}

// Semua mahasiswa pasti ujian
func (m Mahasiswa) ujian(mata_kuliah string) {
	f.Printf("Ujian mata kuliah: %s \n", mata_kuliah)
}

// Semua karyawan pasti gajian
func (k Karyawan) gajian() {
	f.Printf("Gajian: $.%e ", k.salary)
}

// Interfaces untuk yang pelajar
type Pelajar interface {
	makan(makanan string)
	minum(minuman string)
	ujian(mata_kuliah string)
}

type Pekerja interface {
	makan(makanan string)
	minum(minuman string)
	gajian()
}

// Fungsi Di luar interface / ga ada di interface
func (m *Manusia) bikinHoax() {
	f.Printf(m.nama + " Bikin berita Hoax biar kacau...... ")
}

// Main function
func main() {
	f.Println(`بِسْــــــــــــــــــمِ اللهِ الرَّحْمَنِ الرَّحِيْمِ`)

	// Implementasi Struct di atas adalah sebagai berikut

	// 1. Mahasiswa
	joni := Mahasiswa{Manusia{"Joni", 20, "0214353454", "098342342", "jonni@example.com"}, "Prapatan University", "Kosan ibu Nuri", 200}
	var joni_mahasiswa Pelajar // Interface
	f.Println(`Nama:` + joni.nama)
	f.Println(`Nama:` + s.Itoa(joni.umur))
	f.Println(`Nama:` + joni.telepon)
	f.Println(`Nama:` + joni.hanphone)
	f.Println(`Nama:` + joni.email)

	joni_mahasiswa = joni
	joni_mahasiswa.makan(`Nasi padang`)
	joni_mahasiswa.minum(`Es Campur`)
	joni_mahasiswa.ujian(`Sastra Rusia`)
	// Kalo tidak di komen fungsi di bawah akan ada error: joni_mahasiswa.bikinHoax undefined (type Pelajar has no field or method bikinHoax)
	// joni_mahasiswa.bikinHoax() // Ya iya lah masa Mahasiswa bikin Hoax, bego di piara mah ga usah kuliah...
	joni.bikinHoax() //Joni sebagai manusia bisa khilaf, jadi ini akan jalan

	f.Println(``)
	f.Println(`------------------------`)
	f.Println(``)

	// 2. Karyawan
	kokom := Karyawan{Manusia{"Kokom Komariyah", 27, "02199999", "0888902343", "kokok-cute@example.com"}, "PT. Telekokom Tbbek", "Rumah dinas Telekokom", 20000}
	var kokom_karyawan Pekerja // Interface
	f.Println(`Nama:` + kokom.nama)
	f.Println(`Nama:` + s.Itoa(kokom.umur))
	f.Println(`Nama:` + kokom.telepon)
	f.Println(`Nama:` + kokom.hanphone)
	f.Println(`Nama:` + kokom.email)

	kokom_karyawan = kokom
	kokom_karyawan.makan(`Steak Kerbau Buleng`)
	kokom_karyawan.minum(`Vodka Bridenk`)
	kokom_karyawan.gajian()
	f.Println(``)
	// Kalo tidak di komen fungsi di bawah akan ada error: kokom_karyawan.bikinHoax undefined (type Pelajar has no field or method bikinHoax)
	// kokom_karyawan.bikinHoax() // masa Professional bikin Hoax...
	kokom.bikinHoax() //Kokom sebagai manusia bisa khilaf, jadi ini jalan
	f.Println(``)
	f.Println(`----------------------------
	f.Println(``)
	// Manusia biasa
	manusia := Manusia{"Entahlah", 27, "02100", "08000", "teuing@ex.com"}
	f.Println(`Nama:` + manusia.nama)
	f.Println(`Nama:` + s.Itoa(manusia.umur))
	f.Println(`Nama:` + manusia.telepon)
	f.Println(`Nama:` + manusia.hanphone)
	f.Println(`Nama:` + manusia.email)
	manusia.bikinHoax() // Wajar namanya manusia
}