SlideShare a Scribd company logo
GoFFIng around with Ruby
@gautamrege
@joshsoftware
GoFFIng around with Ruby #RubyConfPH
FFI
Foreign Function
Interface
*In stdlib since Ruby 1.9.3
Why do we need FFI?
• Resque / Sidekiq / delayed_job
• 3rd party API requests
• Sending newsletters
• Heavy computation
• Fast searches, aggregation.
Why Go?
• Power of multi-core.
• Goroutines to the rescue
• Language is restricted focussed.
• Programming Ethics
• Compiled
If it compiles, it
works
What is FFI anyway?
• Language interoperability!
• Calling convention.
• libffi.so
• ruby-ffi
• Fiddle (in Stdlib since 1.9.3)
FFI or Good ol’ C-ext?
• FFI Easier to write and maintain.
• Gems are now easier to install -
don’t need build dependencies.
• Portable code
• No more “Building native
extensions…” while installing
gems.
Simple Ruby Code
def race(legs, benchmark)
tids = []
legs.times do |i|
tids << Thread.new(i) do |leg|
array = (1..benchmark).map { |i| i }
p "Done leg #{leg} benchmark #{benchmark}"
end
end
tids.each { |t| t.join }
end
race(4, 50_000_000)
Benchmark - Ruby
$ time ruby run1.rb
Done leg 1 benchmark 50000000
Done leg 0 benchmark 50000000
Done leg 3 benchmark 50000000
Done leg 2 benchmark 50000000
real 0m18.242s
user 0m16.626s
sys 0m1.292s
Simple Go Code
package main
import "fmt"
func race(leg int, benchmark int) {
arr := []int{}
for i := 0; i < benchmark; i++ {
arr = append(arr, i)
}
fmt.Println("Done leg:", leg)
}
func main() {
for i := 0; i < 4; i++ {
race(i, 50000000)
}
}
Simple Go Code
package main
import "fmt"
func race(leg int, benchmark int) {
arr := []int{}
for i := 0; i < benchmark; i++ {
arr = append(arr, i)
}
fmt.Println("Done leg:", leg)
}
func main() {
for i := 0; i < 4; i++ {
race(i, 50000000)
}
}
Simple Go Code
package main
import "fmt"
func race(leg int, benchmark int) {
arr := []int{}
for i := 0; i < benchmark; i++ {
arr = append(arr, i)
}
fmt.Println("Done leg:", leg)
}
func main() {
for i := 0; i < 4; i++ {
race(i, 50000000)
}
}
Simple Go Code
package main
import "fmt"
func race(leg int, benchmark int) {
arr := []int{}
for i := 0; i < benchmark; i++ {
arr = append(arr, i)
}
fmt.Println("Done leg:", leg)
}
func main() {
for i := 0; i < 4; i++ {
race(i, 50000000)
}
}
Benchmark - Go
$ time go run run1.go
Done leg: 0
Done leg: 1
Done leg: 2
Done leg: 3
real 0m2.774s
user 0m2.564s
sys 0m0.929s
Calling Go from Ruby
• Build a C library using Go code.
• Build a FFI extension in Ruby
• Call it !
c-shared Go library
package main
import (
"C"
"fmt"
)
func race(leg int, benchmark int) {
arr := []int{}
for i := 0; i < benchmark; i++ {
arr = append(arr, i)
}
fmt.Println("Done leg:", leg)
}
//export churn
func churn(leg C.int, benchmark C.int) {
for i := 0; i < int(leg); i++ {
race(i, int(benchmark))
}
}
func main() {
}
c-shared Go library
package main
import (
"C"
"fmt"
)
func race(leg int, benchmark int) {
arr := []int{}
for i := 0; i < benchmark; i++ {
arr = append(arr, i)
}
fmt.Println("Done leg:", leg)
}
//export churn
func churn(leg C.int, benchmark C.int) {
for i := 0; i < int(leg); i++ {
race(i, int(benchmark))
}
}
func main() {
}
c-shared Go library
package main
import (
"C"
"fmt"
)
func race(leg int, benchmark int) {
arr := []int{}
for i := 0; i < benchmark; i++ {
arr = append(arr, i)
}
fmt.Println("Done leg:", leg)
}
//export churn
func churn(leg C.int, benchmark C.int) {
for i := 0; i < int(leg); i++ {
race(i, int(benchmark))
}
}
func main() {
}
$ go build -o librun.so -buildmode=c-shared run2.go
Ruby FFI extension
require 'fiddle'
module Fun
def self.race(leg, benchmark)
librun = Fiddle.dlopen(‘./librun.so')
race = Fiddle::Function.new(
librun['churn'],
[Fiddle::TYPE_INT, Fiddle::TYPE_INT],
Fiddle::TYPE_VOID
)
race.call(leg, benchmark)
end
end
Call it!
require './fun'
Fun.race(4, 50_000_000)
$ time ruby run2.rb
Done leg: 0 Benchmark 50000000
Done leg: 1 Benchmark 50000000
Done leg: 2 Benchmark 50000000
Done leg: 3 Benchmark 50000000
real 0m2.776s
user 0m2.719s
sys 0m0.969s
Practical Example
Practical Example
Make Model Variant
Practical Example
Make Model Variant
Practical Example
Practical Example
Insurance
Vendor
Practical Example
Insurance
Vendor
68 columns
Doing the Math!
18 STATES
428 CARS
68 VENDORS
= 523,872 cells
If that was not enough …
For each of the
523,872 cells
Calculate Depreciation
Index in ElasticSearch
for cmake, v := range segments {
for model, j := range v {
for submodel, k := range j {
for insurance, segment := range k {
wg.Add(1)
go func(cmake string, model string,
submodel string, insurance string,
segment string) {
defer wg.Done()
// data := es_data{...}
// prepare_es_data(...)
es_add_depreciation(&data)
}(cmake, model, submodel, insurance, segment)
}
}
}
}
Practical Example
About 350,000 go-routines
for cmake, v := range segments {
for model, j := range v {
for submodel, k := range j {
for insurance, segment := range k {
wg.Add(1)
go func(cmake string, model string,
submodel string, insurance string,
segment string) {
defer wg.Done()
// data := es_data{...}
// prepare_es_data(...)
es_add_depreciation(&data)
}(cmake, model, submodel, insurance, segment)
}
}
}
}
Practical Example
About 350,000 go-routines
Performance Benefits
Performance Benefits
• Sidekiq: 2 GB memory & ~18 minutes
Performance Benefits
• Sidekiq: 2 GB memory & ~18 minutes
• Go FFI: 135 MB memory & 1 minute 13 seconds.
Performance Benefits
• Sidekiq: 2 GB memory & ~18 minutes
• Go FFI: 135 MB memory & 1 minute 13 seconds.
ElasticSearch
indexing took
48 seconds
Complexities of FFI
• Memory Management (alloc / free)
• Pointer management
• Fiddle::Pointer
• Fiddle::Closure
Don’t use them unless you HAVE to!
Resources
• Fiddle http://ruby-doc.org/stdlib-2.0.0/libdoc/fiddle/rdoc/
Fiddle.html
• FFI Core Concepts https://github.com/ffi/ffi/wiki/Core-
Concepts
• Github: ffi/ffi
• Effective Go ( https://golang.org/doc/effective_go.html )
• A Tour of Go ( https://tour.golang.org/welcome/1 )
@joshsoftware
@gautamrege
http://www.codecuriosity.org

More Related Content

PDF
EuroPython 2017 - Bonono - Simple ETL in python 3.5+
PDF
Shared Memory Parallelism with Python by Dr.-Ing Mike Muller
PPTX
Kotlin Basic & Android Programming
PDF
Simple Data Engineering in Python 3.5+ — Pycon.DE 2017 Karlsruhe — Bonobo ETL
PDF
Streams for (Co)Free!
PDF
Simple ETL in python 3.5+ with Bonobo - PyParis 2017
PPTX
Intro to C++
PDF
Dataflow: Declarative concurrency in Ruby
EuroPython 2017 - Bonono - Simple ETL in python 3.5+
Shared Memory Parallelism with Python by Dr.-Ing Mike Muller
Kotlin Basic & Android Programming
Simple Data Engineering in Python 3.5+ — Pycon.DE 2017 Karlsruhe — Bonobo ETL
Streams for (Co)Free!
Simple ETL in python 3.5+ with Bonobo - PyParis 2017
Intro to C++
Dataflow: Declarative concurrency in Ruby

What's hot (20)

PDF
Hourglass Interfaces for C++ APIs - CppCon 2014
PPTX
Connecting C++ and JavaScript on the Web with Embind
PPTX
Blazing Fast Windows 8 Apps using Visual C++
PPTX
Mca 2nd sem u-4 operator overloading
PDF
D vs OWKN Language at LLnagoya
PDF
Take advantage of C++ from Python
PPTX
Mono + .NET Core = ❤️
PDF
Notes about moving from python to c++ py contw 2020
PDF
[GSoC 2017] gopy: Updating gopy to support Python3 and PyPy
PPTX
Lambda Expressions in C++
PDF
Porting legacy apps to Griffon
PDF
Machine learning with py torch
PPT
Take Flight - Using Fly with the Play Framework
PDF
PyPy's approach to construct domain-specific language runtime
PPT
Lecture05
PDF
Happy Go Programming Part 1
PDF
Flamingo Core Concepts
PPTX
Php 7.x 8.0 and hhvm and
PPTX
Queue oop
PDF
«Python на острие бритвы: PyPy project» Александр Кошкин, Positive Technologies
Hourglass Interfaces for C++ APIs - CppCon 2014
Connecting C++ and JavaScript on the Web with Embind
Blazing Fast Windows 8 Apps using Visual C++
Mca 2nd sem u-4 operator overloading
D vs OWKN Language at LLnagoya
Take advantage of C++ from Python
Mono + .NET Core = ❤️
Notes about moving from python to c++ py contw 2020
[GSoC 2017] gopy: Updating gopy to support Python3 and PyPy
Lambda Expressions in C++
Porting legacy apps to Griffon
Machine learning with py torch
Take Flight - Using Fly with the Play Framework
PyPy's approach to construct domain-specific language runtime
Lecture05
Happy Go Programming Part 1
Flamingo Core Concepts
Php 7.x 8.0 and hhvm and
Queue oop
«Python на острие бритвы: PyPy project» Александр Кошкин, Positive Technologies
Ad

Viewers also liked (20)

PDF
インフラ野郎AzureチームOCP Summit US 2017号外
PDF
Qualité, bonnes pratiques et CMS - WordCamp Bordeaux - 18 mars 2017
PDF
[GUIDE] Vigilance sommeil - Guide prévention et santé
PDF
Secure development environment @ Meet Magento Croatia 2017
PDF
Diagnóstico SEO Técnico con Herramientas #TheInbounder
PDF
B2B Marketing and The Power of Twitter
PDF
Deploying Immutable infrastructures with RabbitMQ and Solr
PDF
Charla control parental e IoT v2. Etek.ppsx
PDF
TensroFlow XLA : JIT編 (r1.3版)
PDF
Jeudis du Libre - MySQL comme Document Store
PDF
第5回ue4ハンズオンセミナー
PPT
Understanding P2P
PDF
DNSの運用を考える
PDF
Master the flow of microservices - because your business is more complex than...
PPTX
Solvent Effects on Chemical Reaction
PDF
Fortune 1000 HR Leader Survey Results
PDF
Startups & Gamification (LeanCamp Tehran 2016)
PPTX
Scale Model Humans
PPTX
Fun Core Gym Pdf
PPTX
Discovery, Reuse, Research and Crowdsourcing: IIIF experiences from the NLW
インフラ野郎AzureチームOCP Summit US 2017号外
Qualité, bonnes pratiques et CMS - WordCamp Bordeaux - 18 mars 2017
[GUIDE] Vigilance sommeil - Guide prévention et santé
Secure development environment @ Meet Magento Croatia 2017
Diagnóstico SEO Técnico con Herramientas #TheInbounder
B2B Marketing and The Power of Twitter
Deploying Immutable infrastructures with RabbitMQ and Solr
Charla control parental e IoT v2. Etek.ppsx
TensroFlow XLA : JIT編 (r1.3版)
Jeudis du Libre - MySQL comme Document Store
第5回ue4ハンズオンセミナー
Understanding P2P
DNSの運用を考える
Master the flow of microservices - because your business is more complex than...
Solvent Effects on Chemical Reaction
Fortune 1000 HR Leader Survey Results
Startups & Gamification (LeanCamp Tehran 2016)
Scale Model Humans
Fun Core Gym Pdf
Discovery, Reuse, Research and Crowdsourcing: IIIF experiences from the NLW
Ad

Similar to GoFFIng around with Ruby #RubyConfPH (20)

PDF
Functional go
PDF
Go - techniques for writing high performance Go applications
PDF
Ruby Functional Programming
PPTX
Improving go-git performance
PDF
Something about Golang
PDF
Geeks Anonymes - Le langage Go
PDF
Mirko Damiani - An Embedded soft real time distributed system in Go
PPTX
Data science in ruby is it possible? is it fast? should we use it?
PPTX
Introduction to Ruby Native Extensions and Foreign Function Interface
KEY
Playing Go with Clojure
PPTX
Gopher in performance_tales_ms_go_cracow
ZIP
Rubinius 1.0 and more!
PDF
Writing a Kernel in Rust: Code Quality and Performance by Luc Lenôtre
PPTX
Ruby3x3: How are we going to measure 3x
PPTX
The GO Language : From Beginners to Gophers
PDF
Rubinius For You - GoRuCo
PDF
Funtional Ruby - Mikhail Bortnyk
PDF
Functional Ruby
PPTX
Obscure Go Optimisations
Functional go
Go - techniques for writing high performance Go applications
Ruby Functional Programming
Improving go-git performance
Something about Golang
Geeks Anonymes - Le langage Go
Mirko Damiani - An Embedded soft real time distributed system in Go
Data science in ruby is it possible? is it fast? should we use it?
Introduction to Ruby Native Extensions and Foreign Function Interface
Playing Go with Clojure
Gopher in performance_tales_ms_go_cracow
Rubinius 1.0 and more!
Writing a Kernel in Rust: Code Quality and Performance by Luc Lenôtre
Ruby3x3: How are we going to measure 3x
The GO Language : From Beginners to Gophers
Rubinius For You - GoRuCo
Funtional Ruby - Mikhail Bortnyk
Functional Ruby
Obscure Go Optimisations

More from Gautam Rege (15)

PDF
RubyConf India 2019 - Confessions of a rubypreneur
PDF
Agile india 2017 - Rewarding OpenSource with $$$
PDF
WIDS - Gamifying Open Source
PDF
Gamifying Open Source
PDF
Affordable Smart Housing - The new revolution
PDF
WebSummit 2015 - Gopher it
PDF
Dont test your code
PDF
Art of speaking at tech conferences
PDF
RubyConf Portugal 2014 - Why ruby must go!
PDF
Ruby and rails - Advanced Training (Cybage)
PDF
RedDot Ruby Conf 2014 - Dark side of ruby
PDF
ScotRuby - Dark side of ruby
PDF
GCRC 2014 - The Dark Side of Ruby
PPT
Rails Vs CakePHP
PPT
Ruby On Rails
RubyConf India 2019 - Confessions of a rubypreneur
Agile india 2017 - Rewarding OpenSource with $$$
WIDS - Gamifying Open Source
Gamifying Open Source
Affordable Smart Housing - The new revolution
WebSummit 2015 - Gopher it
Dont test your code
Art of speaking at tech conferences
RubyConf Portugal 2014 - Why ruby must go!
Ruby and rails - Advanced Training (Cybage)
RedDot Ruby Conf 2014 - Dark side of ruby
ScotRuby - Dark side of ruby
GCRC 2014 - The Dark Side of Ruby
Rails Vs CakePHP
Ruby On Rails

Recently uploaded (20)

PDF
How to Choose the Right IT Partner for Your Business in Malaysia
PDF
Raksha Bandhan Grocery Pricing Trends in India 2025.pdf
PDF
Design an Analysis of Algorithms I-SECS-1021-03
PDF
Audit Checklist Design Aligning with ISO, IATF, and Industry Standards — Omne...
PDF
Flood Susceptibility Mapping Using Image-Based 2D-CNN Deep Learnin. Overview ...
PPTX
Odoo POS Development Services by CandidRoot Solutions
PDF
System and Network Administration Chapter 2
PPTX
ManageIQ - Sprint 268 Review - Slide Deck
PPTX
Transform Your Business with a Software ERP System
PPTX
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
PDF
PTS Company Brochure 2025 (1).pdf.......
PDF
Nekopoi APK 2025 free lastest update
PPT
Introduction Database Management System for Course Database
PDF
Addressing The Cult of Project Management Tools-Why Disconnected Work is Hold...
PDF
Digital Strategies for Manufacturing Companies
PPTX
Agentic AI Use Case- Contract Lifecycle Management (CLM).pptx
PDF
Internet Downloader Manager (IDM) Crack 6.42 Build 42 Updates Latest 2025
PDF
top salesforce developer skills in 2025.pdf
PDF
Navsoft: AI-Powered Business Solutions & Custom Software Development
PPTX
history of c programming in notes for students .pptx
How to Choose the Right IT Partner for Your Business in Malaysia
Raksha Bandhan Grocery Pricing Trends in India 2025.pdf
Design an Analysis of Algorithms I-SECS-1021-03
Audit Checklist Design Aligning with ISO, IATF, and Industry Standards — Omne...
Flood Susceptibility Mapping Using Image-Based 2D-CNN Deep Learnin. Overview ...
Odoo POS Development Services by CandidRoot Solutions
System and Network Administration Chapter 2
ManageIQ - Sprint 268 Review - Slide Deck
Transform Your Business with a Software ERP System
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
PTS Company Brochure 2025 (1).pdf.......
Nekopoi APK 2025 free lastest update
Introduction Database Management System for Course Database
Addressing The Cult of Project Management Tools-Why Disconnected Work is Hold...
Digital Strategies for Manufacturing Companies
Agentic AI Use Case- Contract Lifecycle Management (CLM).pptx
Internet Downloader Manager (IDM) Crack 6.42 Build 42 Updates Latest 2025
top salesforce developer skills in 2025.pdf
Navsoft: AI-Powered Business Solutions & Custom Software Development
history of c programming in notes for students .pptx

GoFFIng around with Ruby #RubyConfPH

  • 1. GoFFIng around with Ruby @gautamrege
  • 4. FFI
  • 6. Why do we need FFI? • Resque / Sidekiq / delayed_job • 3rd party API requests • Sending newsletters • Heavy computation • Fast searches, aggregation.
  • 7. Why Go? • Power of multi-core. • Goroutines to the rescue • Language is restricted focussed. • Programming Ethics • Compiled If it compiles, it works
  • 8. What is FFI anyway? • Language interoperability! • Calling convention. • libffi.so • ruby-ffi • Fiddle (in Stdlib since 1.9.3)
  • 9. FFI or Good ol’ C-ext? • FFI Easier to write and maintain. • Gems are now easier to install - don’t need build dependencies. • Portable code • No more “Building native extensions…” while installing gems.
  • 10. Simple Ruby Code def race(legs, benchmark) tids = [] legs.times do |i| tids << Thread.new(i) do |leg| array = (1..benchmark).map { |i| i } p "Done leg #{leg} benchmark #{benchmark}" end end tids.each { |t| t.join } end race(4, 50_000_000)
  • 11. Benchmark - Ruby $ time ruby run1.rb Done leg 1 benchmark 50000000 Done leg 0 benchmark 50000000 Done leg 3 benchmark 50000000 Done leg 2 benchmark 50000000 real 0m18.242s user 0m16.626s sys 0m1.292s
  • 12. Simple Go Code package main import "fmt" func race(leg int, benchmark int) { arr := []int{} for i := 0; i < benchmark; i++ { arr = append(arr, i) } fmt.Println("Done leg:", leg) } func main() { for i := 0; i < 4; i++ { race(i, 50000000) } }
  • 13. Simple Go Code package main import "fmt" func race(leg int, benchmark int) { arr := []int{} for i := 0; i < benchmark; i++ { arr = append(arr, i) } fmt.Println("Done leg:", leg) } func main() { for i := 0; i < 4; i++ { race(i, 50000000) } }
  • 14. Simple Go Code package main import "fmt" func race(leg int, benchmark int) { arr := []int{} for i := 0; i < benchmark; i++ { arr = append(arr, i) } fmt.Println("Done leg:", leg) } func main() { for i := 0; i < 4; i++ { race(i, 50000000) } }
  • 15. Simple Go Code package main import "fmt" func race(leg int, benchmark int) { arr := []int{} for i := 0; i < benchmark; i++ { arr = append(arr, i) } fmt.Println("Done leg:", leg) } func main() { for i := 0; i < 4; i++ { race(i, 50000000) } }
  • 16. Benchmark - Go $ time go run run1.go Done leg: 0 Done leg: 1 Done leg: 2 Done leg: 3 real 0m2.774s user 0m2.564s sys 0m0.929s
  • 17. Calling Go from Ruby • Build a C library using Go code. • Build a FFI extension in Ruby • Call it !
  • 18. c-shared Go library package main import ( "C" "fmt" ) func race(leg int, benchmark int) { arr := []int{} for i := 0; i < benchmark; i++ { arr = append(arr, i) } fmt.Println("Done leg:", leg) } //export churn func churn(leg C.int, benchmark C.int) { for i := 0; i < int(leg); i++ { race(i, int(benchmark)) } } func main() { }
  • 19. c-shared Go library package main import ( "C" "fmt" ) func race(leg int, benchmark int) { arr := []int{} for i := 0; i < benchmark; i++ { arr = append(arr, i) } fmt.Println("Done leg:", leg) } //export churn func churn(leg C.int, benchmark C.int) { for i := 0; i < int(leg); i++ { race(i, int(benchmark)) } } func main() { }
  • 20. c-shared Go library package main import ( "C" "fmt" ) func race(leg int, benchmark int) { arr := []int{} for i := 0; i < benchmark; i++ { arr = append(arr, i) } fmt.Println("Done leg:", leg) } //export churn func churn(leg C.int, benchmark C.int) { for i := 0; i < int(leg); i++ { race(i, int(benchmark)) } } func main() { } $ go build -o librun.so -buildmode=c-shared run2.go
  • 21. Ruby FFI extension require 'fiddle' module Fun def self.race(leg, benchmark) librun = Fiddle.dlopen(‘./librun.so') race = Fiddle::Function.new( librun['churn'], [Fiddle::TYPE_INT, Fiddle::TYPE_INT], Fiddle::TYPE_VOID ) race.call(leg, benchmark) end end
  • 22. Call it! require './fun' Fun.race(4, 50_000_000) $ time ruby run2.rb Done leg: 0 Benchmark 50000000 Done leg: 1 Benchmark 50000000 Done leg: 2 Benchmark 50000000 Done leg: 3 Benchmark 50000000 real 0m2.776s user 0m2.719s sys 0m0.969s
  • 29. Doing the Math! 18 STATES 428 CARS 68 VENDORS = 523,872 cells
  • 30. If that was not enough … For each of the 523,872 cells Calculate Depreciation Index in ElasticSearch
  • 31. for cmake, v := range segments { for model, j := range v { for submodel, k := range j { for insurance, segment := range k { wg.Add(1) go func(cmake string, model string, submodel string, insurance string, segment string) { defer wg.Done() // data := es_data{...} // prepare_es_data(...) es_add_depreciation(&data) }(cmake, model, submodel, insurance, segment) } } } } Practical Example About 350,000 go-routines
  • 32. for cmake, v := range segments { for model, j := range v { for submodel, k := range j { for insurance, segment := range k { wg.Add(1) go func(cmake string, model string, submodel string, insurance string, segment string) { defer wg.Done() // data := es_data{...} // prepare_es_data(...) es_add_depreciation(&data) }(cmake, model, submodel, insurance, segment) } } } } Practical Example About 350,000 go-routines
  • 34. Performance Benefits • Sidekiq: 2 GB memory & ~18 minutes
  • 35. Performance Benefits • Sidekiq: 2 GB memory & ~18 minutes • Go FFI: 135 MB memory & 1 minute 13 seconds.
  • 36. Performance Benefits • Sidekiq: 2 GB memory & ~18 minutes • Go FFI: 135 MB memory & 1 minute 13 seconds. ElasticSearch indexing took 48 seconds
  • 37. Complexities of FFI • Memory Management (alloc / free) • Pointer management • Fiddle::Pointer • Fiddle::Closure Don’t use them unless you HAVE to!
  • 38. Resources • Fiddle http://ruby-doc.org/stdlib-2.0.0/libdoc/fiddle/rdoc/ Fiddle.html • FFI Core Concepts https://github.com/ffi/ffi/wiki/Core- Concepts • Github: ffi/ffi • Effective Go ( https://golang.org/doc/effective_go.html ) • A Tour of Go ( https://tour.golang.org/welcome/1 )