Monday, May 19, 2025

Golf 600.3.25 released

This patch release fixes issues with SELinux on Fedora, Redhat and other Linux distributions that use SELinux. The setup would sometimes not setup policies properly, resulting in denying basic permissions (effectively requiring the use Permissive mode). The new setup should be more reliable according to SELinux documentation.

The setup of type and policies is also now available also for Golf installation in any given folder, i.e. not just for a system-wide installation.

Saturday, May 17, 2025

Golf 600.3.13 released

This release introduces semantic versioning and removes a limit on the number of Golf source files that can be used in an application.

  • Golf is now using semantic versioning (see https://semver.org/) with major, minor and patch version. Increase in those numbers means incompatible, backward compatible features or backward compatible fixes, respectively.  
  • Before this change, a Golf application could typically have a maximum of anywhere between 1000 and 2000 source files, depending on the length of the path leading up to the Golf root directory.This limit has been removed. Golf uses gnu make file function along with gcc "@" feature which allows reading source files from a file, one line at a time. This allows for virtually unlimited number of Golf source files.

Wednesday, May 14, 2025

Golf 534 released

 This Golf release adds some significant new features:

  • Golf can now be installed in any folder, even without root privileges. Of course, installing dependencies still requires root, but Golf itself does not. For instance, you can install Golf in a home directory under its own folder.
  • New "-g" option is added to gg utility to display Golf root, which is the folder where it's installed. For package-installed Golf (such as with apt, dnf etc.), Golf root is an empty string. It's not empty when Golf is installed into a specific folder (see above new feature).
  • Improved error message when using "-r" option in gg to execute command line programs.
  • Added a string concatenation expression, using plus (+) sign to add strings together whenever a string is expected. Strings can now be simply added together (i.e. set-string s = a+b+c).
  • Added "root-directory" clause in get-app statement, which returns Golf root directory (see above).
  • Added better error message if wrong type is used in statements.
  • Added better error message when a handler cannot be used because it's not public.

Tuesday, May 13, 2025

How to write Web Service API with Golf

How to build a Web Service API
This article will show a simple shopping web API with basic functions, such as adding customers, items and orders, as well as updating and deleting them. It's easy to write and easy to understand with Golf; that's the reason code doesn't have much in a way of comments - there's no need.

The API returns a valid JSON reply, even if it's just a single string (such as created ID for a customer, item or order). Listing an order returns a JSON document showing the order details.

If you'd like to be as RESTful as possible, you can use POST, PUT, GET or DELETE request methods. We'll cover that in another post.

The example is an open web service, i.e. it doesn't check for any permissions. You can add that separately (see the multitenant SaaS example).

This example will use PostgreSQL database, but you can use other databases too.
Keep this project in its own directory
We'll create a new directory ("shop") to keep everything tidy. You can call this directory whatever you want. Then we'll create a new Golf application ("shopping"):
mkdir shop
cd shop
gg -k shopping

Setup the database
Create the database "db_shopping":
echo "create user $(whoami);
create database db_shopping with owner=$(whoami);
grant all on database db_shopping to $(whoami);
\q"  | sudo -u postgres psql

Create the "customers", "items", "orders" and "orderItems" tables we'll use:
echo "drop table if exists customers; create table if not exists customers (firstName varchar(30), lastName varchar(30), customerID bigserial primary key);
drop table if exists items; create table if not exists items (name varchar(30), description varchar(200), itemID bigserial primary key);
drop table if exists orders; create table if not exists orders (customerID bigint, orderID bigserial primary key);
drop table if exists orderItems; create table if not exists orderItems (orderID bigint, itemID bigint, quantity bigint);" | psql -d db_shopping

Tell Golf about your database
First thing to do is to let Golf know what database it should use:
echo "user=$(whoami) dbname=db_shopping" > db

This tells Golf that a database "db" is setup (with database user being the same as your Operating System user, and the database name being "db_shopping"). Golf makes this easy by letting you use a given database's native format for client configuration, which you're likely to be familiar with. So if you used MariaDB or SQLite for instance, you would have used their native client configuration files.
Source code for web service
Here are the source code files.

- Add a new customer

Create file "add-customer.golf" and copy the following to it:
 begin-handler /add-customer
     out-header use content-type "application/json"
     get-param first_name
     get-param last_name
     // Add a customer SQL
     run-query @db ="insert into customers (firstName, lastName) \
             values ('%s', '%s') returning customerID" output customerID : \
             first_name, last_name
         @"<<print-out customerID>>"
     end-query
 end-handler

- Add new item for sale

Thursday, May 8, 2025

Random numbers in Golf

Generating random numbers is important in a wide range of applications. For instance, session IDs often use random numbers; they are also used in generating passwords; another example is load balancing where (say instead of round-robin), the next available process to serve a request is chosen randomly; some applications (like gambling) depend on random qualities; any kind of simulation would heavily rely on random numbers; financial and polling applications use random samples to determine outcomes and policies. The list of possible uses is pretty long.

So with that in mind, generating random numbers in Golf is easy. The most common way is random-string statement:
 random-string to rnd
 p-out rnd new-line

By default "rnd" will be a random string of length 20 consisting of digits (0-9) and letters (a-z and A-Z).

You can specify the length desired:
 random-string to rnd length 100

which will generate a random string of length 100.

Tuesday, May 6, 2025

Golf 520 released

This is a minor release that fixes some compilation issues with new gcc 15:
  • Fixed compilation issues with new gcc 15.
Tested on experimental Debian install.

Saturday, May 3, 2025

Working with debug symbols on Fedora etc.

When installing Golf from a package using a package repository like COPR (for Fedora, Redhat, Rocky, Mageia, Amazon Linux etc.), such as like this:

sudo dnf -y install epel-release
sudo dnf -y copr enable golf-lang/golf-lang
sudo dnf -y install golf

then in order to be able to use gdb and step through Golf itself in gdb, you can obtain the debug package and Golf sources.

To get the dnf debug package:

sudo dnf install golf-debuginfo golf-debugsource

gdb will now know how to use both the debug info and the source code. In case somehow that doesn't work, in gdb use "set debug-file-directory /usr/lib/debug/usr/lib/golf" and "directory /usr/src/debug/golf-..." to point to debug files and source code.

This is how you can use gdb with Golf even if you didn't install from source. Of course, installing from source makes it easy, but then you won't have package management, if that matters to you.

And finally, this process is true for any dnf package, not just Golf.

How to install debug symbols for Golf package on Debian/Ubuntu

If you installed Golf from a package using a repository like Launchpad, such as like this:

sudo add-apt-repository ppa:golf-lang/golf -y
sudo apt update
sudo apt -y install golf

then in order to be able to use gdb and step through Golf itself, you can obtain the debug package and Golf sources.

To get the apt debug package, open the source list for Golf (this is for Ubuntu "Noble", the exact path may vary):

sudo vi /etc/apt/sources.list.d/golf-lang-ubuntu-golf-noble.sources 

and then find the instances of "main" used to describe the package, and change it to "main main/debug", so that you get debug packages too. Also, add deb-src as the source. Here's an example if you're using line-by-line sources:

deb https://ppa.launchpadcontent.net/golf-lang/golf/ubuntu noble main main/debug
deb-src https://ppa.launchpadcontent.net/golf-lang/golf/ubuntu noble main main/debug

If you have a 'section-style' sources, then it might look like:

Use case for dnf distro-sync

Upgrading a Linux distro can go smoothly, or sometimes there can be issues. One issue we encountered in our testing pipeline is what seems to be a DNF/RPM issue with basic packages being unavailable, in this case, in a way that prevents even the most basic dependencies from being fulfilled. 

For instance, it may look like this (the actual versions may differ of course, as well as what package is the issue):

Friday, May 2, 2025

Golf 517 released

 Here's what's new in Golf 511:

  • Added proper copyright years to all files, including a script to update automatically.
  • gcc option -Werror (which makes all gcc warning to be errors) is no longer in public builds in order to avoid build failures on variety of compiler versions out there (it's still in testing/debug code to ensure quality). The same goes for compiled Golf applications.
  • Switched to SAX2 interface (in libxml2) for XML parsing.
  • Debugging with gdb is now always possible, even with production binaries. Golf will split debugging symbols for faster run-time, however they can still be used for debugging.
  • Removed postinst for debian.
  • Cleaned up dependencies for debian and rules file.
  • Hardened mgrg (service manager) when the executable to be started exist but isn't accessible yet (such as when locked temporarily).
  • Cleaned up "sudo make uninstall" if version file not present.