Showing posts with label Programming. Show all posts
Showing posts with label Programming. Show all posts

Thursday, January 5, 2023

Add Build info to a Go Binary

Having the build info directly in a binary is useful in helping to identify one binary from aonther especially if you do a lot of compilations.  Manually updating that information in to the source before build is cumbersome and error prone so it's better to automate it.

This can be done in Go using -ldflags with the build command.  For example, if you have a main.go file such as this:

package main                                                                    

import "fmt"
var(
    build string
)

func main() {
    fmt.Printf("build date: %v\n", build)                            
 
)
Then you can build it with -ldflags to change the value of build with the current date when using the go build command:
go build -ldflags "-X main.build=`date`" main.go

Be careful that other parts of your program doesn't change the value during runtime since it is just a variable.

To make it a little safer, you can put the variables into another package and don't allow it to be updated.   You can, for example, create a package called "buildinfo"

package buildinfo                                                                      
                                                                                   
var (                                                                              
    builddate = "0"                                                                
)                                                                                  
                                                                                   
func GetBuild() string {                                                           
                                                                                   
    return builddate                                                               
}                                                                                  

that is called by your main.go:

package main                                                                       
                                                                                   
import (                                                                           
    "fmt"                                                                          
                                                                                   
    "example/buildinfo"                                                                
)                                                                                  
                                                                                   
func main() {                                                                      
                                                                                   
    fmt.Printf("build date: %v\n", build.GetBuild())                                                             
                                                                                
}

You will then build your application with:

go build -ldflags="-X 'example/buildinfo.builddate=`date`'"

Running the program will now output something like this:

build date: Thu Jan  5 12:33:38 PM

Friday, April 9, 2021

Keep Go Module Directory Clean with GOMODCACHE

Go makes downloading projects and their dependencies very easy.  In the beginning there was go get which will download the project source code and its dependencies to $GOPATH/src.  With modules, all the dependencies are downloaded to $GOPATH/pkg/mod.  The ease of downloading and the lack of management control in the go command means that is easy for the two directories to grow in size and to lose track of which project led to the download of a particular package.

I recently started to play around with the Fyne UI toolkit.  I didn't initially know what other packages it would download so I wanted to have Fyne and its dependencies in their own area.  The go command has a flag -pkgdir that is shared by the various commands.

The build flags are shared by the build, clean, get, install, list, run, and test commands:

...

-pkgdir dir

install and load all packages from dir instead of the usual locations. For example, when building with a non-standard configuration, use -pkgdir to keep generated packages in a separate location.

This didn't work as I expected because it didn't seem like it did anything at all.  Using the command

go build -pkgdir /tmp

resulted in all the downloaded package still going to $GOPATH/pkg/mod.

What did work (thanks to seankhliao) is to set the GOMODCACHE variable which sets more then the cache location but also the package location:

GOMODCACHE=/tmp go build

All the downloaded dependency packages will now be downloaded to /tmp rather then $GOPATH/pkg/mod.  

Honestly, I'm not really sure what -pkgdir is really suppose to do.  Maybe it is only for things that the build command generates?  Why does it do when using with go get?

Wednesday, April 7, 2021

Local Go module file and Go tools magic

I really value that when working with Go there are no "hidden magic" in source code.  Go source code are essentially WYSIWYG.  You don't see decorators or dependency injections that might change the behaviors after it is compiled or run that requires you to not only have to understand the language and syntax but also having to learn additional tools' behavior on the source code.  While this is true of the language it is not true of the go command for Go's module system.

I've personally found Go modules to be more confusing then the original GOPATH.  I understand that it solves some of the complaints about GOPATH and also addresses the diamond dependency problem, but it also adds complexity to the developer workflow and under-the-hood magic. Maybe that's to be expected when it is going beyond source code management and adding a whole package management layer on top, but I'd be much happier to have to deal with this added complexity and burden if the solution was complete (how about package clean up so my mod directory isn't growing non-stop?)!

Modules adds the go.mod file that tracks all a project's dependencies and their versions.  This introduces a problem when one is developing both applications and libraries since it is possible that the developer have both the released production version and in-development version of libraries locally.  To point your application at the library without constantly changing the import path in source code, the replace directive can be used, but when committing the code it is not ideal to submit the go.mod with the replace directives in it as it will likely break the build for someone else checking out the code and can expose some privacy data (the local path that might contain the user name).

Now developers have to add the replace directives locally, remove them right before submission and then put them back (without typos!).  Fortunately, in Go 1.14, the go commands (build, clean, get, install, list, run, and test) got a new flag '-modfile' which allows developer to tell it to use an alternative go.mod file.  The allows a production version of go.mod file to not have to be modified during development/debug and a local dev version of go.mod that can be excluded from getting committed (i.e. .gitignored).  

This can be done on a per-project level by adding -modfile=go.local.mod to go [build | clean | get | install | list | run | test]:

go build -modfile=go.local.mod main.go

Note that whatever the file name is, it still has to end on .mod since the tool assumes to create a local go.sum mod based on a similar name as the local mod file except with the extension renamed from .mod to .sum.

To apply the use of go.local.mod globally, update "go env":

go env -w GOFLAGS=-modfile=go.local.mod

go env -w will write the -modfile value to where Go looks for its settings:

Defaults changed using 'go env -w' are recorded in a Go environment configuration file stored in the per-user configuration directory, as reported by os.UserConfigDir.

So the flow that Jay Conrad pointed out in this bug thread would be as follows:

  1. Copy go.mod to go.local.mod. 
  2. Add go.local.mod to .gitignore.
  3. Run go env -w GOFLAGS=-modfile=go.local.mod. This tells the go command to use that file by default.
  4. Any any replace and exclude directives or other local edits.
  5. Before submitting and in CI, make sure to test without the local file: go env -u GOFLAGS or just -modfile=. 
  6. Probably also go mod tidy.

Tuesday, April 6, 2021

Listing installed packages on Fedora with DNF

To list the packages that are user installed:

dnf history userinstalled

To list all installed packages:

dnf list installed

Friday, January 1, 2021

2021 PC - Asus PN50 4800U

Although I was very tempted to build a new desktop PC and get access to all the power goodness of the latest AMD Ryzen, I was hesitant giving up the small form factor that I had with my Shuttle PC DS87.  When the Asus PN50 with the AMD Ryzen 4800U became available I took the plunge.

The specs comparison between the previous and new PCs:

New PC:

  • Ryzen 7 4800U [Zen2] (8 cores / 16 threads, base clock 1.8GHz, max 4.2GHz - 8 GPU cores - RX Vega 8, 15W)
  • 32 GB Crucial DDR4 3200Mhz  RAM (2x16GB)
  • 1TB Samsung 970 EVO Plus (M.2 NVMe interface) SSD
  • 500GB Crucial MX500 SATA SSD (2.5")
  • Intel WIFI 6, BT 5.0

Previous PC:

  • Shuttle PC DS87
  • Intel Core i7-4790S Processor (8M Cache, base clock 3.2 GHz, max 4.0GHz, 65W)
  • Samsung 850 EVO 500GB 2.5-Inch SATA III Internal SSD (MZ-75E500B/AM)
  • 2 x Crucial 16GB Kit (8GBx2) DDR3 1600 MT/s (PC3-12800)

There are enough sites giving benchmarks so I'm not going to try to repeat what they've done, but I wanted to have something to show myself a tangible performance improvement.  It is generally during compilation when I wish things would go faster so why not compare compilation between the two systems?  The multi-core (8 vs 4) and multi-thread (16 vs 8) should benefit compilation even if the base clock of the 4800U is 1.8GHz while the i7 is 3.2GHz.  I'm expecting modern CPU is also more efficient per clock cycle then an 6 year old CPU.

I decided to time the compilation of OpenCV using the following

wget -O opencv.zip https://github.com/opencv/opencv/archive/master.zip
unzip opencv.zip 
mkdir -p build && cd build
cmake ../opencv-master/
time cmake --build .

i7 Results

real   28m57.219s
user   26m48.466s
sys     2m01.402s

4800U Results

real     36m48.166s
user     34m54.722s
sys       1m52.574s

How did this happen?  Was it that the 3.2-4.0 GHz too much for the 1.8-4.2GHz to overcome?  It did seem like during compilation all of the i7 cores was running at around 3.6 GHZ, but I suspected that the compiler was not actually taking advantage of all the cores of the 4800U.

I tried again using Ninja which automatically configures the build to use the multi-core CPUs.

make clean
cmake -GNinja ../opencv-master/
time ninja

i7 Results

real	11m28.741s
user	85m39.188s
sys	 3m23.310s

4800U Results

real      6m39.268s
user     99m03.178s
sys       4m8.597s

This result looks more like what I expected.  More of the system cycles were used on both the i7 and 4800U as more cores and threads were utilized but the real time was much shorter.  This just shows that for a lot of consumers fewer cores but faster clock speeds might be better for desktops (laptops and battery life adds another dimension) as they rely on the applications to be programmed to take advantage of the multiple cores.  That's why gamer systems usually will give up more cores for faster clock speeds since games aren't known for utilizing multiple cores.

Friday, November 27, 2020

Building GUI applications with Go (Golang)

Go is my favorite programming language.  I have mostly used it for writing command line programs or server-side services so I was not familiar with using it for writing GUI desktop applications.  Questions about using Go for writing GUI applications come up periodically on Reddit or Hacker News with some saying that Go is not appropriate for GUIs while others argue the opposite.  

I decided to take an existing command line program that I've written and put a graphical interface on it using different GUI frameworks/tool kits that are available.  The program's purpose is very simple.  It checks for the latest stable version of Go for your system and if there is a newer version then it downloads it.  Once the file is downloaded, it verifies the checksum to make sure that it correctly downloaded a good file.  The UI will simply show the information (where to save, the version to download, the checksum) and a button to start downloading.  During download, a progress bar indicates what is happening. 




The code can be found at https://github.com/lazyhacker/getgo with the GUI files in the internal/gui package.  gtk.go and fyne.go are for GTK and Fyne respectfully.

TLDR;

Go is perfectly capable for writing GUI application as far as functionality.  There are tried-and-true toolkits such as GTK and QT and emerging ones such as Fyne and Gio.  The former being more polished but with an extra layer of non-Go code between the app and the graphics layer and a higher learning curve.  The latter's tooling, visualization documentation and functionality are less developed.  

Where all of the options fall behind some other languages is in its developer friendliness in the form of documentation.  

GTK do have a lot of documentation and many users who have posted answers on forums, but the documentation is based on another programming language.  

Gio and Fyne are more lacking in documentation and tutorials so it can be more frustrating for beginners looking to learning or find answers.  Although the general concepts might be more easily understood since they aren't as big of a system as GTK.

All the toolkits I tried rely a lot of providing code examples as a form of teaching, but the examples aren't very well documented or discoverable making them less friendly to developers.

Binary size for my simple program are:
  • command-line only ~6M
  • command-line + GTK GUI ~9M
  • command-line + Fyne GUI ~14M
GTK does require for the shared libraries to be available on the system (they aren't compiled into the above binary) so they will need to be bundled in.

It took me about a day to write the Fyne version and about 2 days for the GTK version.  I also had to spend a day to figure out how to get both to compile and run on Windows.

Choices

There are actually many choices available to Go developers for building GUIs.  I think the perception that Go isn't a "GUI" language could be because:
  1. A number of GUI projects have been abandoned.  
  2. There is no single "blessed" GUI framework from the Go team.  
  3. There are no fully native Go implementation of a GUI toolkit.  
(1) I don't think this is unusual given the complexity of developing a GUI framework that there are a lot of abandoned GUI projects.  What is more important is what is available that is actively maintained since there are always many abandoned projects in any language so don't let the noise give you the wrong impression.

(2) Although there are some languages that comes with a GUI toolkit as part of the language (e.g. Java, Swift), most language don't.  Go can feel like its a "batteries included" language with its rich standard libraries (e.g. it basically comes with a HTTP server) so with no GUI options it could lead to the misconception that the Go team doesn't believe that Go should be used for GUI apps.  However, a lot of languages don't have one either (C/C++, Python, etc.)

(3) This really depends at what is the definition of a fully native Go implementation:  
  • Can app developers everything in Go?  Can it be written in an idiomatic way?
  • Can the entire project just depend on the Go tool chain?
  • Is the whole tech stack built with Go?
With the exception of the tool kits whose philosophy are to combine Go for backend logic and another language for the front-end GUI (e.g. javascript), most of the options let the developer write everything in Go.  The Go tool chain includes cgo for interfacing with C code so even if the toolkit is dependent on C libraries (e.g. OpenGL, GTK/Qt, etc.) the app developer don't really have to deal with other tool chains except maybe have some be installed for cgo to access. 

Having the whole stack be written in Go is not realistic.  With the exception of C, every language at some point have to deal with the lower level of the system (whether it be the graphics subsystem or OS) that is written in another language).  

Personally, as long as everything I write is in Go and only the Go tools are used than that is "native" enough for me.  As an applications layer developer, I don't expect to be working on the GUI underpinnings that would require to combine languages and tool chains.  That means there are plenty of options for Gophers (developers that uses Go ) and my evaluation criteria is on some subjective qualities such as how intuitive it is and whether it is easy to learn/use, and some quantitative attributes such as stability. 

With this in mind, the most often mentioned options are Qt, GTK, Fyne and Gio.  Between Qt and GTK, I chose GTK.  Both are these are popular production-level GUI toolkits written in C/C++.  The reason I picked GTK is that I use Linux and Gnome and the admittedly self-perception that installing GTK is easier then installing a Qt dev environment.

I also wanted to try either Fyne or Gio as these are two toolkits that were built with Go.  Both rely on go-gl (which in turn depends on OpenGL) to deal with the graphics subsystem to draw the interface and widgets so they don't that extra layer between the app and graphics system being occupied by another framework like GTK and Qt.


Gio (https://gioui.org)

The first GUI toolkit that I tried to look at is Gio.  It wholeheartedly embraced everything Go and the latest-and-greatest.  It allows compiling to desktops, mobile, and WASM (web assembly).   It supports Go modules (common) and drops GOPATH support (uncommon).   Its embrace of immediate mode GUI programming is kind of Go-like in its belief that it's not always necessary to give up control to a framework.

Installing Gio to be ready to use is very easy.  Make sure the system already installed the wayland/X11 and OpenGL development libraries.  A simple 1-line install from dnf, apt or whatever Linux package manager will likely suffice.  Then it is a simply importing the package in your Go code and during the first compile, Go will pull down Gio and all its dependencies through Go modules.

However, I quickly moved away from Gio for a couple of reasons:
  1. It lacked documentation to help a new user understand how to use it and I found the existing documentation to poorly organized.  It primarily relies on code examples and API comments and then leaves it to the users to figure out for themselves how to use it.
  2. While immediate mode gives more control to the developers, building GUIs is one area where there's enough complexity that I don't necessarily mind handing it off to a toolkit to take care of things.  I wonder whether immediate mode is actually more useful to developers who build GUI tool kits then developers who use the tool kits.
I might come back to Gio some day when I have more time to learn it.


Fyne (https://fyne.io)

Fyne is a more standard retained-mode GUI tool kit that is easy to install.  It is similar to Gio in that you just need to use your package manager to install the graphical development libraries and then just import Fyne to have it download all the necessary packages and dependencies.  Unlike Gio, it also support the traditional GOPATH method if you don't use Go modules.

The document was much more comprehensive feature an quick beginning walk-through, tutorials and API documentation.  What holds by Fyne a little is in the organization of the documentation which required me to do quite a bit of jumping between sections to understand something.  For example, one section talks about a widget but it is somewhere else where it shows what the widget actually looks like.

I was able to put together a basic interface pretty quickly with Fyne thanks to its basic tutorials.  While getting something working quickly is a plus, I'll admit that I did not find the graphical elements very attractive.  It seems to be embracing material design in some form but feels like it's incomplete.  Extending the look and feel is also difficult at the moment. 

Although I mentioned that I got a working GUI up quickly, I was immediately met with a bug.  The app would start and all the components would draw in the window before it would suddenly turn blank.  Resizing or hovering over a particular widget would bring the interface back.  I only saw this on my Linux system.  I reported this to Fyne and got a response pretty quickly asking me for more info and some follow up questions.  It's good that the Fyne developers are keeping an eye on bug submissions!


Microsoft Windows 

To compile and run on Windows basically requires installing Windows version of gcc.  Fyne's install instructions gives 3 options (msys2+MingW-64, TDM, and Cywin) for GCC.  I went with msys2 + mingw64 as msys2 is also the recommended way to install GTK.

Once msys2 was installed, I installed the mingw64 gcc package through the msys2 shell:

> pacman -S mingw-w64-x86_64-toolchain base-devel

Note: If you want to use the GCC outside of the MingW shell (e.g. with cmd.com), you need to add:
  • C:\msys2\mingw64\bin
  • C:\msys2\usr\bin
to the Windows PATH variable.

After getting MingW GCC installed, I tried to compile and promptly ran into a compilation error about undefined references.  After much digging, I found the solution to be deleting the go-build cache that is in %USERPROFILE%/AppData/Local/go-build.


Gotk3 (https://github.com/gotk3/gotk3)

To use GTK 3 with Go requires gotk3 which provide Go bindings to GTK's APIs (including glib, gdk, and others).  There is also go-gtk which provides GTK 2 binding.

gotk3 has installation instructions on its wiki.  Installing on Linux and MacOS is very simple similar to Gio and Fyne.  For Windows, as with Fyne, it requires installing msys2 + mingw-64.

Although GTK has extensive documentation and tutorials, it's mostly for C or Python.  gotk3's documentation, unfortunately, consists of mainly of comment that is just the C function name.  It doesn't even provide a link to the C documentation so you're required to find it yourself.  For the few APIs that has it's own gotk3 comments, they dropped the C function name so you will have to figure what the Go function maps to. 

gotk3 also follows the "read the code" school of teaching.  Here they have a directory of example code but little explanation of what it is an example of of.  The user is left to decipher all the example codes to form an idea of how the gotk3 works and what is available.   What I ended up doing was to go through and learn GTK in C first and then try to map the concepts to the gotk3 APIs.    This isn't the most friendly way to introduce a Gopher to GUI development with gotk3 but might be okay for a C GTK developer coming to Go.

Of course, on my very first compilation, I get an error message:

go: finding module for package github.com/gotk3/gotk3/gtk
go: found github.com/gotk3/gotk3/gtk in github.com/gotk3/gotk3 v0.5.0
# github.com/gotk3/gotk3/gtk
../../gopath/pkg/mod/github.com/gotk3/gotk3@v0.5.0/gtk/gtk.go:5369:14: _Ctype_struct__GIcon can't be allocated in Go; it is incomplete (or unallocatable)

Fortunately, there was already a bug filed and a solution was already committed.  I had to force Go to use a newer version of gotk3 then what's has been tagged as the stable version:

**Update for go 1.16 4/3/2021**  Another bug came up when trying to use go 1.16 and it looks like a fix made it to the master branch so the same workaround for the previous bug will now also work.

In the project directory:

go get github.com/gotk3/gotk3/gtk@master 




Microsoft Windows

While getting GTK installed on Linux was trivial, it takes a bit more effort on Windows, but the GTK page is very clear.  If you'll be doing everything within msys then there's not much more to do.  If you want to use build in another terminal such as cmd, then you'll need to add the mingw bin path to the %PATH% variable.

There seems to a compatibility issue between gotk3 and GTK that requires remove the -Wl flag from gdk.3.0.pc which is captured in the gotk3 wiki for installing on Windows.

Saturday, March 14, 2020

Google App Engine's Missed Opportunity

I've been a fan of Google's App Engine (GAE) since its initial release in 2008 but it has never quite taken off despite the growth of running applications in the cloud and the rise of open source software.  It's really a missed opportunity for Google.

I have been running many small projects on GAE which is now part of Google Cloud's offerings.  GAE is friendlier to start with than other hosting options from Google in that it has a free tier which I suspect is sufficient for most users.  GAE auto-scales as traffic increases so there is a possibility that it could surpass the free quota but users can set a guidance on the max daily spend.  This has generally worked for me as I set the max to be $0.00 so that I don't go past the free quota.  Be aware that this is not a hard limit so there is a chance that it can go over the limit.  Recently, I got billed $0.01 requiring me to log in to Google Cloud and pay the amount due.  Since I had to log into the developer console, it gave me a chance to look at the projects that I've been running.  The majority were simple static websites which as simple as GAE is to use, it's easier to use something like Github pages.  Both offers SSL (HTTPS support) and custom domains so I decided to move my sites off of GAE.

This move got me thinking about the missed opportunity for Google with GAE.  It is not because GAE should be a static web hosting site since GAE is about running applications hosted in the cloud.  GAE offers a simple and complete solution that was perfect for users of open source projects. 

Just as Github Pages is a super simple solution to host static web pages, GAE started as a super simple solution for running cloud applications.  GAE is basically a server, database, memory cache, sign-in and storage solution all-in-one.  Users don't have to select and install each of these basic components themselves.  This meant that an open source project could be developed where the user can easily run it by putting it on GAE with the same simplicity of desktop projects (possibly even easier).  I imaged a world where someone can write a note taking app in App Engine and anyone who wants to use it get the source, put it on GAE and it's running and ready to use!   We see note taking programs all the time running on desktops and mobile because the author knows that if the user installs the binary they can start using the app, but for cloud apps it always involves a lot of infrastructure setup.  The reaction to this has been Docker containers which I find is still harder on the user and a lot more complex for the developer.

When GAE was first launched it confused developers who weren't used to this paradigm for web development and Google didn't do a very good job explaining or addressing some missing/problematic areas.  It seems like Google focused more on Enterprises to switch to this "Platform-As-A-Service" model when they have less need for such hand-holding.  I believe the missed opportunity is that they missed out that this was more ideal for the consumer market then the enterprise market.

Sunday, June 10, 2018

Go with WebAssembly Early Examples

WebAssembly (WASM) is the most exciting technology in web development in a long time from my perspective.  It represents the first true steps in breaking the monopoly of Javascript as the language for the browser even though the WASM folks emphasize that isn't the intention.  In my previous post, I mention that Go will support compiling to WebAssembly in version 1.11.  This post shares some of my experimentation with Go's WASM support and to see what might be possible.  Let me emphasize that the code is very hacky.  I wrote them quickly mainly so I can try out WASM. 


There are multiple ways to use WASM for web applications:

  1. Optimization for JavaScript-driven applications - This is the scenario most emphasized for the current level functionality provided by the initial (MVP) release of WASM.  Instead of writing everything in pre-compiled Javascript, optimized WASM modules are called by JavaScript.  These modules can be written in JavaScript or other languages that can compile to WASM.
  2. Porting existing code bases over to the browser - This is most often demonstrated with porting existing C/C++ code bases over to WASM through Emscripten and running what might previously been an exclusively desktop/native app (e.g. Autocad, games, etc.).
  3. Writing an web app completely in a non-Javascript language - This is what I'm most excited about!  Instead of having Javascript be the primary language, the application is completely written in another language such as Go.  At the time of this writing, this isn't completely possible since WASM doesn't support WASM modules from directly calling the browser APIs (e.g. DOM APIs, XHR, etc.).  This will be coming and is currently covered under the Host Binding proposal for WASM.  Until then, the Javascript can be abstracted away in a language-specific binding.
The current state of Go WASM doesn't fit the first scenario very well.  There doesn't seem to be a way to expose methods individually for Javascript to call directly.  The Javascript code can execute each Go program's main function and when main() is done the module is done running.  Given that each WASM module has the complete Go runtime including garbage collection, I'm not sure how practical it is to have a bunch of Go programs that are essentially meant to be single methods to the Javascript code.

Go WASM does provide the ability to define callback methods and attach callbacks to browser events.  This requires that the module is running because once it exists it's not longer available to the browser call call.  Because of this, Go WASM is currently most appropriate for scenarios 2 & 3.

The browser executes Javascript and WASM in a single threaded manner.  When the WASM module is running, the browser's front end will block until it is completed.  This will appear to the end user as if the browser is frozen: no way to type input, click button, etc.  With Go WASM, control is given back to the browser when using time.Sleep or when the Go code is blocked.  This has to be done manually by the developer so it's important to keep it in mind.  Unless the apps expect to have completely control of everything in the browser while it is running developers need to remember to periodically sleep itself to give some control back to the browser.   I hope this gets improved in the future because it makes the code ugly, error prone and honestly isn't something developers should need to do in a multi-tasking environment.

Example 1

Complete source is here. See it running here.  

This is a very basic example of writing a Go WASM module that defines a method that gets attached to a HTML button's click event, change some attributes of the document's elements, waits a few seconds then executes a Go routine that draws to the canvas in the browser.  The keepalive() function prevents the module from quitting until it gets a quit signal that happens when the Quit button is clicked and the cbQuit method is invoked because the button click event is triggered.  Also note that when the browser's Alert dialog is triggered, it blocks everything until it is dismissed whether it's called by JavaScript or by the Go code.

The keepalive() can also simply be
select {}
if the intention is just not let the module exit.

--- ---
The basics of having Go drive the web page (rather then it being Javascript) is all there.

Example 2

Complete source here.  Running example here.

This example was inspired by what was presented at GopherCon by Hana Kim when gomobile was first announced.


Instead of re-writing Rob Pike's Ivy Interpreter for Android/iOS/command-line the example showed that the existing Go library was reused.  Just like her example, this example shows that existing Go libraries can be used in WASM.

--- ---

The resulting WASM module is about 4MB but when compressed, the whole web app was only about 1 MB.

This example really doesn't show anything that the previous example didn't already show. I wanted to try against a larger code base and didn't want to write it myself.  It mainly just demonstrates an existing Go library being used with no changes needed to make it work.

The Ivy code is easy to port but if something is expecting to access a file system or make HTTP calls then the browser environment doesn't match.  There isn't any standard file system and outbound calls uses XHRHttpRequest rather then the current HTTP package.

Conclusions


It is possible to use Go to write web applications even though it currently still needs to rely on JavaScript to access the brower's APIs.  Things like Go routines work but developers have to handle sleeping themselves in order to not block the UI.  However, the possibility of ending JavaScript's monopoly for being the browser's language is definitely there!

Browsers themselves still need to do some optimizations.  Each WASM module's byte code still has to be compiled so there's always a delay before the module starts running.  It still starts faster then JavaScript but it'd be much better if the browsers caches the compiled WASM the first time.  My understanding that it'll likely come in the near future but not there yet.

I'm very excited to see this land in Go 1.11 and look forward to see what other developers use it for!

Sunday, May 20, 2018

WebAssembly (WASM) with Go

This is the first time that I've tried to compile the Go compiler so I figure that I'll document it here for others who might be wanting to try WASM with Go before the official Go release in August.

The next release of Go (1.11) is scheduled for Aug and it will be first time WebAssembly (WASM) will be supported.  WASM will be a build target much like how one builds a binary for other machine and operating systems except that in this case the machine is a "virtual" machine that runs inside the browser.

I've been very excited for WASM and I've been eagerly waiting for the time when I can use Go to write WASM.  The branch for the 1.11 release has is now locked for only bug fixes so I figured that it might be a good time to try writing a WASM code with Go.

Note that this first release for WASM isn't going to be "production" ready.  I don't think it'll be very optimized and WASM itself is only at its MVP release it doesn't allow WASM code direct access to the DOM or the browser APIs so all calls is still going through JavaScript.

Unfortunately, as of this writing, the code in the Go repo doesn't work for WASM.  The work on WASM for Go is primarily being done by Richard Musiol (neelance), the author of GopherJS, so I decided to get the version Go from this GitHub repo.

First, you will need a version of Go on your system to compile the source.  The easiest way is to download and install the binary distribution from the main Go website.

Until 1.11 is released to get WASM is to build from source.

git clone https://go.googlesource.com/go
cd go
Once you have the source, it's time to compile it.

cd src
./all.bash
If everything is built correctly then there will be a new "go" binary in ../bin.  Also, there are two files to help you get started with loading future WASM files in ../misc/wasm.

Create a test.go file:

package main

func main() {
    println("hello, wasm")
}
Compile to WASM with:

GOOS=js GOARCH=wasm go build -o test.wasm test.go
Make sure you're running the go command that you've just built and not the version that you installed originally.

In the same directory with your test.wasm file, copy over wasm_exec.html and wasm_exec.js from misc/wasm.

The browser will expect the test.wasm file to be served with a MIME of application/wasm so you'll need to add the following to your /etc/mime.types file:

application/wasm wasm
To run it in your browser, you'll need to have a web server.  Creating one with Go is easy, or you can also use Python with the following command.

python -m SimpleHTTPServer

Point your browser to your web server and load wasm_exec.html.  Click on the button and you should see "hello, wasm" appear in the browser's console.

I've been experimenting with WASM here.

Sunday, July 16, 2017

My First GopherCon


Being a member of the Go team allowed me to attend my first GopherCon in Denver from July 13 to July 15. This is the 4th GopherCon to be held and previously I’ve only watched the recordings of the sessions on the Gopher Academy Youtube Channel.

Thursday, June 8, 2017

Moving from Blogger to Hugo

I really liked Blogger and I’ve hosted my blog on it since 2011. It was free (still is), but still had all the essentials features for a blog at the time and I like that it was integrated with Google.
My blogging needs haven’t changed since then but the world have evolved and Blogger no longer have all the essential features necessary for a blogging platform. Specifically, I’m talking about Blogger’s lack of support for SSL/TLS for custom domains. I could accept the dated editor controls, quirkiness in the WYSIWYG UI, and limited customization of themes, but there’s no excuse for not having https enabled on a web site anymore.
I’ve now moved Lazy Hacker Babble from Blogger to Hugo + Google App Engine. Hugo is a static site generator written in Go. It takes your markdown file and generates an entire web site consisting of static files so it doesn’t require databases runtimes, extra libraries, etc. Since it’s written in Go, Hugo comes as a stand-alone binary so there is no need to install a bunch of extra software in order to run it.

Wednesday, June 7, 2017

Setting up HTTPS on App Engine With a Custom Domain

The Go programming language provides a great tool, go get, to fetch packages.  A common use case is to get a package that is hosted on Github:

Saturday, April 1, 2017

Accessing Github Through SSH As Different Users

To set up access to Github using different accounts, start by creating ssh keys for each account.

$ cd ~/.ssh
$ ssh-keygen -t rsa -C "github-acct1" -f "github-acct1"
Then add the ssh key to the Github account.

Next, create ~/.ssh/config to tell ssh when to use which account (set permission to be 600):

# Github account #1                                              
Host github.com-acct1                                                                 
   HostName github.com                                                          
   User git                                                                     
   IdentityFile ~/.ssh/github-acct1                                           
                                                                                
# Github account #2                                                         
Host github.com-acct2                                                        
   HostName github.com                                                          
   User git                                                                     
   IdentityFile ~/.ssh/github-acct2

Check out a repo as the user to use by matching to the Host value in ~/.ssh/config:

$ git clone git@github.com-acct1:repo
Change to the repo directory and set the name and email to use for commits if needed.

$ cd repo
$ git config user.name "Acct1"
$ git config user.email acct1@example.com

To avoid accidentally using the wrong account (e.g. default):

$ git config --global --unset user.name
$ git config --global --unset user.email
$ git config --global user.useConfigOnly true
If you get an error message about the user (or the wrong user) not having the right permission to access the repo:

$ eval "$(ssh-agent -s)"
$ ssh-add

Thursday, July 21, 2016

Updating VIM for Go (Golang) Development

Since my last post, setting up Vim for Go development is not only easier but also makes developing with VIM much more powerful.  Just a single plugin, vim-go, is all that is needed for the Go-specific stuff and a host of new tools is now available to handle things like refactoring, linting, error checking, and more.

Go Tools

Make sure that you have Go installed and then get the various Go tools.

goimports

Go provides a lot of use packages that can be imported but it doesn't like it when you import a package and not use it.  Goimports will automatically insert the right imports for you by looking at your code and will remove unused imports from your source.  It's a great time saver!

go get golang.org/x/tools/cmd/goimports
godef

Godef lets you jump to the location where a symbol is defined.

go get -v code.google.com/p/rog-go/exp/cmd/godef
go install -v code.google.com/p/rog-go/exp/cmd/godef
golint

Golint will lint your source and warns you of potential issues.
go get github.com/golang/lint/golint
gorename

Gorename helps to refactor Go code.

go get golang.org/x/tools/cmd/gorename
errcheck

Errcheck checks your code for actual errors that isn't just lint issues.

go get github.com/kisielk/errcheck
gocode

Gocode provides autocomplete of your Go code.  When combined with vim-go and YouCompleteMe plugins, it allows autocomplete to appear as you're typing.


go get -u github.com/nsf/gocode (-u flag for "update")
It's a bit different for Windows so follow the instruction from the link for more details.

gotags

Gotags generate tags for Go code.  Combined with Tagbar, it will provide a pretty display of the tags in your code.

go get -u github.com/jstemmer/gotags
Guru

Guru is a tool that integrates with editors to help it understand Go code.

go get golang.org/x/tools/cmd/guru
go build golang.org/x/tools/cmd/guru

Oracle (Deprecated and replaced by Guru)

Oracle is a source analysis tool for Go program.


go get code.google.com/p/go.tools/cmd/oracle

Vim Plugins

It used to be that you would manually install a vim plugin for each of the various Go tools as well as using the the plugins that comes with Go itself.  Now, everything has been consolidated into a single Vim plugin, vim-go, and that's all you really need when it comes to Go-specific plugins.  A few other plug-ins such as Tagbar and YouCompleteMe are useful to complement your development environment, though.  I highly recommend that you use Vundle to manage your plugins.

vim-go

Vim-go brings together all the various plug-ins and feature for Go development in VIM including autocomplete, snippet support, improved syntax highlighting, go toolchain commands, etc. in a single package.

YouCompleteMe

YCM is a fast code completion engine for VIM that works as you type.  YCM requires VIM 7.3.584 or above and CMake (you'll need to compile the extension after it's downloaded).

Tagbar

A great way to view the tags in your code.  This requires that you have Exuberant Ctags and gotags installed.

Bufexplorer

My favorite plugin for navigating between VIM buffers.

.vimrc


" Go Specific Stuff
                                                             
au BufRead,BufNewFile *.go set filetype=go                                     
autocmd FileType go setlocal softtabstop=4
autocmd FileType go setlocal shiftwidth=4
autocmd FileType go setlocal tabstop=4

" go-def settings
let g:godef_split=2
let g:godef_same_file_in_same_window=1

" go-vim settings
let g:go_fmt_command = "goimports"
let g:go_highlight_functions = 1
let g:go_highlight_methods = 1
let g:go_highlight_structs = 1

" tagbar settings                                                                  
let g:tagbar_type_go = {
    \ 'ctagstype' : 'go',
    \ 'kinds'     : [
        \ 'p:package',
        \ 'i:imports:1',
        \ 'c:constants',
        \ 'v:variables',
        \ 't:types',
        \ 'n:interfaces',
        \ 'w:fields',
        \ 'e:embedded',
        \ 'm:methods',
        \ 'r:constructor',
        \ 'f:functions'
    \ ],
    \ 'sro' : '.',
    \ 'kind2scope' : {
        \ 't' : 'ctype',
        \ 'n' : 'ntype'
    \ },
    \ 'scope2kind' : {
        \ 'ctype' : 't',
        \ 'ntype' : 'n'
    \ },
    \ 'ctagsbin'  : 'gotags',
    \ 'ctagsargs' : '-sort -silent'
\ } 

Sunday, January 10, 2016

Tools of the Trade

Here is what I have in my professional toolkit. These are things that I always try to have on my system. Everything here is free with many them being open source. I originally published this list about 15 years ago and this year I finally revisited it and cleaned things up. What I discovered was that the open source projects are the ones that most likely survived the test of time.
See my posts on recommended books

Programming Languages

  • Go Programming Language - Open source programming language that makes it easy to build simple, reliable and efficient software (Quoted from the Go site but is pretty accurate). This is my favorite language as it blends the compile nature of C with the practical aspects of a scripting language.
    • Check this post on setting up Vim for Go.
  • GNU GCC - Open source C/C++ compiler supported on so many platforms now that I can’t list them on. There’s even ports of it so that you can compile games to run on the GBA. C is the foundation language of enabled the growth of our profession and is a must learn of every software engineering.
  • Perl - One of the great scripting languages although admittedly I rarely use it now. In many instances, Python has taken the mantel of Perl, but Go might replace both.
  • Scheme - I don’t really do much with Scheme, but I believe it’s worthwhile for engineers to have exposure to this form of programming.
  • Polymer Project - For web front-end development Javascript, for better or worst, is the defacto language of the browser, but if building anything beyond the most basic web site, you’ll probably need to use some kind of JavaScript library or framework. I like using the Polymer library since it embraces web components.

Programmer’s Editor

  • Vim - Although I started as an EMACs user, VIM is now my primary editor..
  • GNU EMACS - EMACS is more then an editor, it’s a way of life!
  • Notepad++ (Windows)

Web Browser

Databases

  • PostgreSQL - Top notch standards-compliant RDBMS
  • FreeToad - GUI client for accessing Oracle databases.

Multimedia

  • VideoLAN VLC - Open source media player that can play just about any format without the hassle of installing a bunch of codecs individually.
  • Handbrake - Allows conversion between different media formats.

Graphics

  • SketchUp - 3D modeling program. SketchUp Make is the free version. (not open source)
  • Blender - Open source 3D modler ala Maya.
  • IrfanView (Windows) Fast graphic view that’s small, fast, but loaded with features.
  • GIMP - Photoshop-like graphics program.
  • Inkscape - Vector graphics editor.

Source Control

Communications

  • Pidgin
  • Weechat
  • IRC

Operating Systems

Cloud

Windows/DOS