The GoLand Blog : A cross-platform Go IDE with extended support for JavaScript, TypeScript, and databases | The JetBrains Blog https://blog.jetbrains.com Developer Tools for Professionals and Teams Fri, 16 Jun 2023 17:22:17 +0000 en-US hourly 1 https://blog.jetbrains.com/wp-content/uploads/2023/02/cropped-icon-512-32x32.png The GoLand Blog : A cross-platform Go IDE with extended support for JavaScript, TypeScript, and databases | The JetBrains Blog https://blog.jetbrains.com 32 32 GoLand 2023.2 EAP #5 Is Out with an Intention Action to Update Dependencies in go.mod   https://blog.jetbrains.com/go/2023/06/16/goland-2023-2-eap-5/ Fri, 16 Jun 2023 17:22:14 +0000 https://blog.jetbrains.com/wp-content/uploads/2023/05/Blog_Featured_image_1280x600_GoLand-2x-1.png https://blog.jetbrains.com/?post_type=go&p=364449 The fifth GoLand 2023.2 EAP build is now available!

You can get it via the Toolbox App, download it from our website, use a snap package (for Ubuntu), or from inside GoLand, select Check IDE updates for: Early Access Program in Settings | Appearance & Behavior | System Settings | Updates.

Download GoLand 2023.2 EAP

Intention actions to update dependencies in go.mod 

We’ve added several intention actions and inspections to help you update dependencies in go.mod files faster. 

Now, when you open your go.mod file, GoLand highlights outdated dependencies. You can hover over the highlighted versions of a given package and use a quick-fix to update it.

You can also update all dependencies to their patches or latest major versions, and there is an option to update only direct dependencies.

The outdated dependencies are highlighted thanks to the Dependency update available inspection. We’ve also added two more inspections: 

  1. Deprecated dependency shows deprecated dependencies in strikethrough text.
  1. Retracted dependency version shows retracted version numbers in strikethrough text.  

You can manage these inspections, including their scope and severity, in Settings / Preferences | Editor | Inspections | Go modules.

Version control systems

Option to commit specific lines of code

GoLand 2023.2 EAP 5 introduces a highly anticipated feature to selectively commit specific parts of code chunks. To perform a partial commit, select the lines within a chunk and call Include these lines into commit from the context menu. The chunk will be divided into individual lines with the selected ones highlighted. You can add or exclude lines from the selection using checkboxes or the context menu. 

Docker 

Preview of files inside Docker image layers 

It is now easy to access and preview the contents of a Docker image layer in the Services view. Select the image from the list, select Show layers, and click Analyze image for more information. You can then view a list of the files stored in the layer and easily open a selected file in the editor by right-clicking on the file and calling the Open File (or Download File for binaries) option. 

Set Docker container to run as a Before Launch task for run configurations

It is now possible to set a Docker run configuration to run before another configuration by designating it a Before Launch task. The IDE will wait for the container that is currently running to be healthy, and then it will launch the next run configuration. To set up a queue, first create a required Docker run configuration and then add it to the container via Modify options | Add before launch task | Run configuration.

Kubernetes 

Support for multiple kubeconfig files within a single project 

We have introduced a new feature that allows you to set up multiple kubeconfig files within a single project. This simplifies the experience of handling multiple clusters or working with environments on different clusters in the same project. To set the files up, go to File | Settings | Build, Execution, Deployment | Kubernetes. 

Ability to view deployment logs

You can now view logs for deployments in Kubernetes clusters from the Services tool window. Right-click on Deployment in the tree and then select Follow Log or Download Log from the context menu. 

That’s it for today! We’d love to hear what you think about the new features. Get in touch with us on Twitter, leave your comments here, open an issue in our tracker, or drop us a message in the Gophers Slack #goland channel. Thanks!

]]>
File Sorting by Modification Time, Pinned Run Configurations, and the Kafka Plugin in GoLand 2023.2 EAP #4  https://blog.jetbrains.com/go/2023/06/09/goland-2023-2-eap-4/ Fri, 09 Jun 2023 16:07:06 +0000 https://blog.jetbrains.com/wp-content/uploads/2023/05/Blog_Featured_image_1280x600_GoLand-2x-1.png https://blog.jetbrains.com/?post_type=go&p=362423 The fourth GoLand 2023.2 EAP build is now available!

You can get it via the Toolbox App, download it from our website, use a snap package (for Ubuntu), or from inside GoLand, select Check IDE updates for: Early Access Program in Settings | Appearance & Behavior | System Settings | Updates.

Download GoLand 2023.2 EAP

User experience

File sorting by modification time in the Project view 

GoLand 2023.2 EAP 4 brings the long-awaited option to arrange your files in the Project view based on their modification time. This new functionality automatically reorders the files whenever the changes in your project are saved. To enable this feature, open the three dots menu in the Project view and then select Tree Appearance | Sort by Modification Time.

Pinned run configurations in the Run widget

To make managing multiple run configurations easier, we’ve implemented the option to pin preferred configurations in the Run widget. To add a run configuration to the Pinned section, open the three dots menu next to its name and select Pin. If you have multiple pinned configurations, you can easily rearrange them by dragging and dropping within the list.

The Kafka plugin

The new Kafka plugin lets you monitor your Kafka event streaming processes. You can: 

  • Connect to a Kafka cluster.
  • Produce and consume messages in different formats, including Avro and Protobuf.
  • Manage topics and monitor consumer groups.
  • Use Confluent Schema Registry and AWS Glue Schema Registry.

You can find more details on the Documentation page

That’s it for today! We’d love to hear what you think about the new features. Get in touch with us on Twitter, leave your comments here, open an issue in our tracker, or drop us a message in the Gophers Slack #goland channel. Thanks!

]]>
GitLab Integration, Improved Main Toolbar Customization, Text Search in Search Everywhere, and More in GoLand 2023.2 EAP #3 https://blog.jetbrains.com/go/2023/06/02/gitlab-integration-2023-2-eap-3/ Fri, 02 Jun 2023 08:29:39 +0000 https://blog.jetbrains.com/wp-content/uploads/2023/05/Blog_Featured_image_1280x600_GoLand-2x-1.png https://blog.jetbrains.com/?post_type=go&p=358885 The third GoLand 2023.2 EAP build is now available!

You can get it via the Toolbox App, download it from our website, use a snap package (for Ubuntu), or from inside GoLand, select Check IDE updates for: Early Access Program in Settings | Appearance & Behavior | System Settings | Updates.

Download GoLand 2023.2 EAP

GitLab integration 

GoLand 2023.2 EAP 3 introduces initial integration with GitLab, allowing you to work with the Merge Request functionality right from the IDE.

User experience

Improved main toolbar customization

We’ve expanded the customization options for the new UI’s main toolbar. You can now use a dropdown menu to quickly choose actions that you want to add to the toolbar. To do so, right-click on any widget, select Add to Main Toolbar, and explore the available options.

Single-click navigation between project directories

In the Project view, there’s a new Open Directories with Single Click option that makes expanding and collapsing the project folders quicker and more responsive. The option is available from the drop-down menu once you click on the three dots icon.

Text search in Search Everywhere

The Search Everywhere (Double ⇧ / Double Shift) functionality, primarily utilized for searching through files, classes, methods, actions, and settings, now includes text search capabilities similar to Find in Files. With this enhancement, text search results are displayed when there are few or no other search results available for a given query. The feature is enabled by default and can be managed in Settings/Preferences | Advanced Settings | Search Everywhere.

Light theme with light header in the new UI

For v2023.2, we’ve refined the user experience with the Light theme by introducing the alternate Light with Light Header option, featuring matching light colors for window headers, tooltips, and notification balloons.

Syntax highlighting in inspection descriptions 

In Settings / Preferences | Editor | Inspections, we’ve implemented syntax highlighting for code samples, which facilitates comprehension of any given inspection and its purpose.

Suggested plugins in Settings/Preferences

To make it easier to configure the IDE for your specific projects and extend its functionality with plugins, we have updated the UI for the Settings/Preferences | Plugins section. It now includes a set of suggested plugins that is automatically defined based on your project specifics and appears at the top of the list.

That’s it for today! We’d love to hear what you think about the new features. Get in touch with us on Twitter, leave your comments here, open an issue in our tracker, or drop us a message in the Gophers Slack #goland channel. Thanks!

]]>
User Experience and Performance Improvements in GoLand 2023.2 EAP #2 https://blog.jetbrains.com/go/2023/05/19/user-experience-and-performance-improvements-in-goland-2023-2-eap-2/ Fri, 19 May 2023 11:02:30 +0000 https://blog.jetbrains.com/wp-content/uploads/2023/05/Blog_Featured_image_1280x600_GoLand-2x-1.png https://blog.jetbrains.com/?post_type=go&p=356949 The second build of the 2023.2 Early Access Program is available! 

You can get it via the Toolbox App, download it from our website, use a snap package for Ubuntu, or from inside GoLand, select Check IDE updates for: Early Access Program in Settings | Appearance & Behavior | System Settings | Updates.

Download GoLand 2023.2 EAP

Error message for Migrate function parameter to method receiver

In the previous build, we introduced two new refactorings – Migrate function parameter to method receiver and Migrate method receiver to function parameter. These help you turn a function parameter into a method receiver and vice versa. 

Migrate function parameter to method receiver is impossible in cases where the first parameter is not a valid receiver type, like in the case of an interface type. 

To clarify why the refactoring is not performed in such instances, we’ve added a helpful message explaining why the refactoring is impossible or undesirable. 

Here’s an example with generics. 

User experience

Reworked hamburger menu in the main toolbar on Windows and Linux

We’ve refined the behavior of the hamburger menu in the new UI that is located in the main toolbar for Windows and Linux. Once you click on the menu icon, the elements now appear horizontally over the toolbar.

Also, there’s now an option to turn this menu into a separate toolbar. For this, go to View | Appearance | Main Menu as a Separate Toolbar.

Performance 

New tool for easily generating shared indexes

We’re introducing a new command line tool for quickly building and uploading shared indexes. It is designed to streamline teamwork and eliminate time wasted on locally indexing large projects.

The new tool simplifies the process of generating shared indexes for your team, requiring just a few clicks instead of multiple scripts and services. 

The workflow is straightforward: Download the archive, unzip it, and execute the binary file via the command line, specifying the project path. The tool will then configure an intellij.yaml file that you need to add to your project.

For more comprehensive customization, check out the scripts provided in README.md.

Web development

If you’re interested in web development updates, read this blog post from the WebStorm team. GoLand supports WebStorm features, either out of the box or through plugins.

That’s it for today! We’d love to hear what you think about the new features. Get in touch with us on Twitter, leave your comments here, open an issue in our tracker, or drop us a message in the Gophers Slack #goland channel. Thanks!

]]>
OS in Go? Why Not? https://blog.jetbrains.com/go/2023/05/16/os-in-go-why-not/ Tue, 16 May 2023 13:21:23 +0000 https://blog.jetbrains.com/wp-content/uploads/2023/05/DSGN-16534-Blog-Featured-image-1280x600-2x.png https://blog.jetbrains.com/?post_type=go&p=351813 This article was written by an external contributor.

Aniket Bhattacharyea

Mathematics postgraduate who has a passion for computers and software.

Website

Operating systems are the heart and soul of a computer system. The operating system manages the computer’s hardware as well as software resources and provides the user with a means to interact with the computer. Traditionally, languages like C and Assembly have been used to write operating systems because of their low overhead and “close to the machine” features. But the rise of high-level languages such as Go has introduced features that should make developing complex software such as an OS much easier. For example, features like type safety, error handling, and concurrency can be advantageous when writing an OS. These features suggest that a high-level language like Go would be a natural choice for OS development. So, why isn’t it?

In this article, you’ll learn why languages like C have a stronghold over OS development and whether writing an OS using Go is possible.

Why are OSs or kernels written in C and assembly?

Determining which language was used to write any particular operating system can be challenging because every OS is written in a combination of multiple languages.

An operating system comprises different components with different responsibilities and can be written in different languages. The heart of an OS is the kernel – the component responsible for interacting with the hardware—which is almost always written in C or assembly. The user-facing components, such as the GUI apps, can be written in any language. For example, Android uses Java for the userland components, such as the GUI framework and system apps like Camera, Phone, etc. In contrast, the kernel is written in C and assembly, and the low-level system components, such as the libraries, are written in C++.

This article focuses explicitly on whether Go is a good candidate for writing the kernel of an OS. Almost all major kernels are written in C, with bits of assembly in between. There are a few reasons why C rules the kernel world:

  1. Direct memory management: The selling point of C is that it allows the programmer to manipulate memory directly. While manual memory management can be daunting in general when you’re writing a kernel, you want as much control over memory as possible, and C gives you precisely that. Concepts like memory-mapped I/O, DMA controllers, page tables, swapping, and more all require memory manipulation, which is possible with C.
  2. Lack of abstraction: C has no complex data structures like hashes, trees, or linked lists, and should the programmer require them, they are expected to implement their own. This provides more granular control over the code, as the programmer can tweak the details of the implementation as needed for efficiency.
  3. No runtime needed: Unlike Java and Python, C requires no runtime. You only need a mechanism to call the main() function, and C will happily run. This means you can run C programs directly on the hardware without struggling with memory management, process management, etc.
  4. Portability: C has been ported to many different CPU architectures, making it an excellent choice for writing kernels that support multiple architectures.

However, C itself is usually insufficient for writing an entire kernel, as there are cases where you need to write assembly code:

  1. When manually written, assembly can be better than what the compiler produces. Some operations can be hard to implement in C, and the compiler-produced machine code can be convoluted or inefficient. In that case, writing assembly manually is a better choice.
  2. Some code is impossible to write in C. For example, when task switching in C, it’s impossible to save the registers onto the stack or save the stack pointer into the task-control block because C provides no direct access to the stack pointer.

Why can Go be an alternative language for OS development?

High-level languages like Go offer some desirable features that, on the surface, make them seem like an excellent choice for OS development:

  1. Certain types of bugs are much less likely in a high-level language. Buffer overruns and use-after-free bugs are virtually impossible in languages like Go. Even C code written very carefully by expert programmers inadvertently includes bugs like this. The use-after-free bug is so common that the Linux kernel consists of a memory checker to detect some use-after-free and buffer overrun bugs at runtime.
  2. Handling concurrency is easier in high-level languages, as almost every high-level language comes with the mechanisms necessary to handle concurrency built in.
  3. The type safety of a language like Go can protect against C’s relaxed type enforcements.

Why is Go not used in OS/Kernel development?

Though Go offers desirable features that can make the life of an OS developer easier, it also has a few limitations.

As a language with garbage collection, Go isn’t really suited for OS development. Writing a kernel in Go means tiptoeing around Go’s garbage collection by writing code carefully in order to minimize heap usage. As explained in this Reddit thread, mouse lag is likely because the interrupt handler allocates memory that triggers garbage collection.

Go also requires an extensive runtime to execute, which means it can’t be run directly on the hardware. Although TinyGo can compile Go to run on bare metal, it supports only a tiny amount of architecture compared to C, which can be run on virtually any architecture.

Another related issue is that syscalls make up a large number of the operations in a typical Go runtime. The runtime communicates with the OS for various operations, such as writing a file or starting a thread. However, when you’re writing an OS, you have to implement these operations on bare metal and hack the Go runtime to call your implementations. The question then boils down to whether you really want to spend so much time and effort on hacking the runtime, whereas other languages like C allow you to start writing the OS immediately.

As you’ll see, it isn’t impossible to write an OS in Go. However, writing a non-toy OS that can be used by general users is nearly impossible. It’s easy to write an OS that boots on a single architecture and drops into a shell, but using Go to write an OS that runs on multiple architectures, supports different devices such as video cards or network cards, and is maybe POSIX-compliant would be very challenging. You can definitely omit some of those features, but that would limit the viability of the OS.

Operating systems written in Go

Although Go isn’t the most suitable choice for OS development, this doesn’t mean that writing an OS in Go is impossible, and many research projects are exploring how this can be done.

Biscuit is an OS written in Go that runs on the 64-bit X86 architecture. It uses a modified implementation of the Go 1.10 runtime, where more assembly code has been added to handle boot and entry/exit for syscalls and interrupt handlers. The boot block, written in assembly, loads the Go runtime and a “shim” layer. The Go runtime expects to communicate with an underlying kernel for various functions. Since there’s no underlying kernel, the “shim” layer provides these functions.

Biscuit provides user processes with a POSIX interface, with support for fork, exec, etc. It implements a file system supporting the core POSIX file system calls. Biscuit implements a TCP/IP stack and a driver for Intel PCI-Express Ethernet NICs written in Go. Using POSIX interfaces, Biscuit can run many Linux C programs without modifying the source code.

Biscuit, however, lacks many features such as scheduling priority, swapping out to page or disk, and security features like users, access control lists, and address space randomization.

More details about Biscuit can be found in the white paper.

gopher-os is another proof-of-concept kernel written in Go. Like Biscuit, it uses assembly to set up a Go runtime and load the kernel. However, it’s still in the early stages of development and hasn’t received any updates since 2018. It’s also broken on the latest versions of Go.

Clive is another unikernel written in Go, but it doesn’t run on bare metal, and a modified Go compiler is used to compile Clive software.

gVisor is an application kernel written in Go that implements the Linux system API in sandbox containers.

Conclusion

Even though C is the dominant language when it comes to OS development, Go offers features like type safety, automatic memory management, and concurrency, giving it the potential to be an excellent choice for OS development. However, a lack of fine-tuned control over the runtime and different aspects of the language, coupled with the popularity of C, make it challenging for Go to gain a foothold in the OS development world. However, some research OSs have been written in Go, and we can expect consumer-friendly OSs to be written in Go in the near future.

]]>
https://blog.jetbrains.com/zh-hans/go/2023/05/16/os-in-go-why-not/
The GoLand 2023.2 Early Access Program Has Started! https://blog.jetbrains.com/go/2023/05/12/the-goland-2023-2-early-access-program-has-started/ Fri, 12 May 2023 16:51:46 +0000 https://blog.jetbrains.com/wp-content/uploads/2023/05/Blog_Featured_image_1280x600_GoLand-2x.png https://blog.jetbrains.com/?post_type=go&p=353764 Today marks the beginning of GoLand’s second Early Access Program for 2023. Check out our roadmap blog post for what we have planned for v2023.2.

You can get this EAP build via the Toolbox App, download it from our website, use a snap package (for Ubuntu), or from inside GoLand, select Check IDE updates for: Early Access Program in Preferences / Settings | Appearance & Behavior | System Settings | Updates.

Download GoLand 2023.2 EAP

If you’re not familiar with our EAPs, here’s a brief overview:

EAP builds let you try out the latest features and enhancements in GoLand while we continue to work on them. These builds are not fully tested and might be unstable, but this is where you can help us. By taking these builds and their new features for a test drive with your real-world projects and scenarios, you can help us polish them. This way, the IDE will work more smoothly for you when the final version is released.

  • The EAP lets you be among the first to try the newest features.
  • EAP builds are free to use for 30 days from the build date. You can use this period as an extended trial of GoLand.
  • We provide a series of EAP builds until a stable release is almost ready. For version 2023.2, the EAP period will last until mid-July.
  • In each release cycle, we reward the most active evaluators and people who helped us improve GoLand by sharing their product experience, feedback, and suggestions. We give them a complimentary one-year GoLand subscription.
  • New builds come out almost every day. If you don’t want to wait for the official EAP build announcements, you can download our nightly builds, available only via the Toolbox App. Note that nightly builds often do not meet the quality standards for official EAP builds and don’t come with release notes. Like EAP builds, they expire within 30 days of being released.

Now let’s look at what’s new in this EAP build.

Optional ability to download modules automatically

To download Go modules dependencies in a project in GoLand, you need to manually apply a quick-fix. Failing to apply the quick-fix may result in red code in newly opened projects, which can be confusing, and some users want GoLand to run go mod download automatically. The discussion about whether it would be better to download dependencies automatically has continued for some time.

In this build, we’ve implemented the ability to download modules automatically on project open and after each change of the go.mod file. This functionality is on by default, but you can turn it off at any time in Settings/Preferences | Go | Go Modules.

Migrate function parameter to method receiver

We have two new refactorings – Migrate function parameter to method receiver and Migrate method receiver to function parameter.

The Migrate function parameter to method receiver refactoring can be useful when you’ve implemented several functions and then realized that you’d rather have a type and convert all of the functions into methods on this type instead.

Migrate method receiver to function parameter is for when you’ve implemented a type and several methods on that type, but you then decide that you’d prefer to have several separate functions instead.

Completion for ‘make’ function arguments

We’ve added type-aware completions for make function invocations.

Checks for ‘make’ function arguments

GoLand can now detect errors and redundant arguments in make functions. There is also a quick-fix to remove redundant arguments, which you can access via Alt+Enter (⌘⌥), as usual.

Option to disable vendoring 

You can now disable vendoring per project, for example, when you have a monorepo containing the vendor folder used by another language. You can disable vendoring while creating a new project or anytime by going to Preferences/Settings | Go | Go modules.

VS Code keymap is bundled

If you’re accustomed to the VS Code keymap, you can now choose it in the Customize section on the Welcome screen. You can also change the keymap in Preferences/Settings | Keymap.

The receiver type is shown in completion for method expressions

If you’re calling a method directly on a type (this is called a method expression), you need to provide the receiver type as the first argument. GoLand now shows the receiver as the first parameter in completion suggestions for these cases.

Generics: Improved error message for missing arguments

The error message for missing type arguments in the type’s instantiation has been improved. Now, GoLand explicitly tells you what’s wrong.

Preview for the Wrap error handling in a closure intention

We’ve added a preview for the Wrap error handling in a closure intention.

The preview appears when you open the list of available intention actions and hover over an option. This feature lets you instantly see how your code will be altered once you apply the IDE’s suggestions.

You can disable the preview feature by pressing Ctrl+Q / F1 while the list of intention actions is open, and it will remain disabled until you turn it back on in the same way.

Warning for redundant conditions in ‘for’ loops 

GoLand now shows a warning message for redundant conditions in for loops. There is also a quick-fix to remove the redundant condition. You can access the quick-fix via Alt+Enter (⌘⌥).

Notable bug-fixes

GO-10198 – Incorrect receiver with built-in type is detected, as expected.

That’s it for today. We’d love to hear what you think about our new features. Get in touch with us on Twitter, leave your comments here, open an issue in our tracker, or drop us a message in the Gophers Slack #goland channel. Thanks!

]]>
Comparing database/sql, GORM, sqlx, and sqlc https://blog.jetbrains.com/go/2023/04/27/comparing-db-packages/ Thu, 27 Apr 2023 09:43:46 +0000 https://blog.jetbrains.com/wp-content/uploads/2023/03/Blog_Featured_image_1280x600-11.png https://blog.jetbrains.com/?post_type=go&p=337349 This article was written by an external contributor.

Rexford A. Nyarko

Rexford A. Nyarko

Rexford Nyarko is a solution architect with a background in software and network systems, cloud environments, server administration, and various database technologies. Rexford particularly enjoys explaining technical concepts to non-technical audiences.

LinkedIn Twitter

Go is known for its simplicity, performance, and complete standard library. Out of the box, Go’s library supports many common operations that many other languages need third-party libraries to perform or may not even support at all. These operations are contained in various packages that handle features such as concurrency, networking, I/O, and text processing.

database/sql is a standard library package responsible for connectivity and interaction with databases (mostly SQL relational ones). It provides generic interfaces, types, and methods for SQL-like interactions. Though it supports many essential modern database features, such as transactions and prepared statements, it also has some limitations. For example, it suffers from a type limitation in which large uint64 values cannot be passed to statements as parameters.

This article compares the database/sql package with 3 other Go packages, namely sqlx, sqlc, and GORM. The comparison of these 4 tools focuses on 3 main areas:

  • Features – Core features are explored, including what makes the tools unique and what they lack.
  • Ease of use – Comparative ease of use is demonstrated using code samples performing the same operations for each tool.
  • Performance/speed – Performance is measured by benchmarking a few database operations using the tools from the standard library’s testing package.

Features

This section looks at the features offered by each package. This comparison uses the base features of the database/sql package as the minimum requirement in terms of features, as all the packages were created to expand the functionality provided by the default package.

database/sql

database/sql was created with simplicity in mind, configured to support the most basic but necessary functionality for interacting with SQL-like databases.

To interact with database management systems, database packages need the appropriate drivers. Currently, database/sql supports a list of over 50 database drivers, covering the most popular DBMSs such as SQLite, MySQL/MariaDB, PostgreSQL, Oracle, and MS SQL Server.

This package also supports features such as basic CRUD operations, database transactions, named parameters, returning multiple result sets, cancellable queries, SQL type support, connection pool management, parameterized queries, and prepared statements.

sqlx

sqlx was created to extend the features of the standard library database package. Since it relies on the database/sql package, all of the features provided by that are also available, including support for the same set of database technologies and drivers.

Outside of these core features, sqlx shines in the following ways:

  • Prepared statements with named parameters – These enable you to use the names of struct fields and map keys to bind variables in a prepared statement or query.
  • Struct scanning – This allows you to scan query results directly into structs for a single row without having to individually scan each field or column, as is the case with database/sql. It also supports scanning into embedded structs.
  • Select and Get – These are convenient methods for handling queries expected to return multiple records or a single record into a slice of a struct or a single struct, respectively. No need to loop on result sets!
  • Support for IN queries – This allows you to bind a slice of values as a single parameter to an IN query. The slice is spread out with the same number of bindvars in the expected places, compared to database/sql treating the slice as a single value.
  • Named queries – This binds the names of struct fields to column names, avoiding the need for positional references to column names when assigning values to bindvars.
  • Error-free result sets: Result sets do not return with errors, which allows for chainable operations on returned results, such as scanning results directly into a struct. This can be seen in the following snippet:
var p Place
err := db.QueryRowx("SELECT city, telcode FROM place LIMIT 1").StructScan(&p)

These are only a few examples of the many features of the sqlx package that ensure a better working experience than database/sql.

sqlc

sqlc is an SQL compiler bundled as an executable binary file and can generate type-safe code for your raw SQL schema and queries. So, you don’t have to write any boilerplate code other than your actual SQL statements.

According to the documentation, it can generate code for PostgreSQL, MySQL/MariaDB, and SQLite. However, the generated code also works with the standard library’s SQL package; therefore, it can use all supported drivers but not necessarily supported databases. Aside from supported databases and drivers, the following are some of its other features:

  • Query annotations – These are various annotations that allow you to define the name of the function for each query and the type of result expected from the query. These are used during code generation to determine the name and signature of the function.
  • JSON tags – sqlc supports the generation of JSON tags for structs or types that will be marshaled and sent to clients as JSON.
  • Schema modifications – sqlc has support for reading various formats of migration files to modify schema and generate code to reflect those changes.
  • Struct naming – sqlc provides options for naming schemes used to generate struct names from table names.

If you’re good with SQL statements and prefer not to use much code to perform database operations and handle the data, this is definitely your package.

GORM

GORM is a full-featured object-relational mapper (ORM) library for the Go language. It lets you write queries as Go code by calling various methods on objects, which GORM translates into SQL queries when interacting with the database. It provides a rich set of features for database interactions, some of which are listed below:

  • Databases and drivers – According to the official documentation, GORM supports MySQL/MariaDB, PostgreSQL, SQLite, SQL Server, and ClickHouse. It also provides the drivers for these database systems. All the same, you may pass on an existing database/sql connection to it, opening it up to possible compatibility with all other databases and drivers supported by the database/sql package.
  • Migrations – GORM supports database migration management for modifying schemas or reverting changes. It makes various provisions for that, such as being able to create tables from structs.
  • Relationships – You can define database relationships using models or structs with annotations in tags and nested structs. One-to-one, many-to-many, and one-to-many relationships can be achieved.
  • Transactions – GORM provides support for transactions, nested transactions, committing and rolling back transactions, etc.
  • Database resolver – This allows you to access multiple database and schema sources in one application. This also allows connection switching (automatic and manual) depending on the struct you’re accessing or database availability and load balancing.
  • SQL builder – The provided SQL builder supports various forms of SQL and SQL clauses. These include but are not limited to CRUD operations, subqueries, prepared statements, named arguments, upserts, SQL expressions, joins, etc.
  • Hooks – These are interfaces that can be implemented to undertake certain activities before or after a DML statement is executed.

This is a non-exhaustive list of this package’s features; it has a wide range of other features that ensure it performs well in almost any use case.

Ease of Use

To maximize productivity, it’s important that a library is easy to use for both experienced developers and newbies. This section looks at how easy it is to get started with each library, considering the available documentation, tutorials (textual and video), and community support. This section also looks at code samples for a few common operations and the learning curve involved.

The code samples for this section are provided in examples directory in this repository on GitHub. To run the code samples, you can connect to a database in GoLand. You can use MySQL or MariaDB for this. Make sure that you have either of those installed.

To connect to a database, open the Database tool window, click on the plus icon, and choose Add data source.

Provide a name for this database connection you’re setting up and all the necessary credentials for your setup. This example uses localhost as the host, default MySQL/MariaDB port 3306, a user called theuser, a hidden password of value thepass, and a database named thedb. GoLand will suggest downloading the necessary drivers if they haven’t been downloaded before. Finally, click on the Test Connection link at the bottom-left of the screen. This will validate the credentials by trying to establish a connection to the specified database using the user and password credentials you provided.

Hopefully, you have connected to your database. Now you can run the setup.sql script – just open it and press on the green arrow at the top left corner or press ⌘⏎ /Ctrl+Enter to execute statements.

If everything went smoothly, you will see your table in the tables list. You can click on the students table twice to see the rows.

database/sql

For experienced developers, database/sql has detailed, technically advanced documentation. Additionally, there’s a great tutorial for beginners. The syntax is quite simple, but you’ll need to check for errors often, which means more code. As the go-to package in the standard library, it also has a huge following and strong support from the entire Go dev community.

If you’re comfortable writing your own SQL queries, this package is a good option, especially for basic queries and basic types or structs with a small set of fields.

The following snippet demonstrates how to use the database/sql package with the MySQL driver to insert a record:

// Function to add a record and return the record ID if successful, if not then an error
func addStudent(s Student) (int64, error){
    // Insert statement listing all the fields and providing their respective values 
    query := "insert into students (fname, lname, date_of_birth, email, gender, address) values (?, ?, ?, ?, ?, ?);"
    result, err := db.Exec(query, s.Fname,s.Lname, s.DateOfBirth, s.Email, s.Gender, s.Address)
    if err != nil {
        return 0, fmt.Errorf("addStudent Error: %v", err)
    }
    // Check to get the ID of the inserted record
    id, err := result.LastInsertId()
    if err != nil {
        return 0, fmt.Errorf("addStudent Error: %v", err)
    }
    return id, nil
}

As you can see, the insert operation is very similar to writing direct SQL statements. You’ll also see that you need to type each field and its associated value separately. Unfortunately, maintaining the code in large structs or complex types becomes cumbersome over time and increases the chance of introducing errors, which may only be caught during runtime.

The snippet below demonstrates how to retrieve multiple records using the database/sql package:

// Function to fetch multiple records 
func fetchStudents() ([]Student, error) {
    // A slice of Students to hold data from returned rows
    var students []Student
    rows, err := db.Query("SELECT * FROM students")
    if err != nil {
        return nil, fmt.Errorf("fetchStudents %v", err)
    }
    defer rows.Close()
    // Loop through rows, using Scan to assign column data to struct fields
    for rows.Next() {
        var s Student
        if err := rows.Scan(&s.ID, &s.Fname, &s.Lname, &s.DateOfBirth, &s.Email, &s.Address, &s.Gender ); err != nil {
            return nil, fmt.Errorf("fetchStudents %v", err)
        }
        students = append(students, s)
    }
    if err := rows.Err(); err != nil {
        return nil, fmt.Errorf("fetchStudents %v", err)
    }
    return students, nil
}

In the snippet above, after fetching the records, you loop through them, use row.Scan() to individually scan each field of each record into a struct, then append the struct to a slice. You need to be careful, as the number of fields in the struct provided must equal the number of fields in the records returned. You should also note that it’s difficult to work with queries using the IN clause, as it treats IN bindvar values as a single value and not multiple values.

sqlx

sqlx also provides detailed technical documentation. As it’s mainly an extension of the Go database/sql package, there’s also a comprehensive guide on using this package with database/sql.

On GitHub, sqlx boasts over 12,800 stars, indicating a strong following and a very active issue list.

If you’re coming from a database/sql background, you’ll have a smooth transition, as queries are similar in syntax and compatible. From the snippets below, you’ll notice quite a lot of similarities with the database/sql code seen earlier, especially the insert statement:

// Add inserting student record using the sqlx package
func addStudent(s Student) (int64, error){
    query := "insert into students (fname, lname, date_of_birth, email, gender, address) values (?, ?, ?, ?, ?, ?);"
    result := db.MustExec(query, s.Fname,s.Lname, s.DateOfBirth, s.Email, s.Gender, s.Address)
    id, err := result.LastInsertId()
    if err != nil {
        return 0, fmt.Errorf("addStudent Error: %v", err)
    }
    return id, nil
}

There are fewer lines of code than with database/sql, due to the reduced need for error checking using the db.MustExec() method.

The code below shows how to retrieve multiple records using the sqlx convenience method:

// Function to fetch multiple records 
func fetchStudents() ([]Student, error) {
    // A slice of Students to hold data from returned rows
    var students []Student
    err := db.Select(&students,"SELECT * FROM students LIMIT 10")
    if err != nil {
        return nil, fmt.Errorf("fetchStudents %v", err)
    }
    return students, nil
}

As you can see, compared to using db.Query() to write syntax compatible with database/sql and looping through the results, sqlx provides much simpler and cleaner code to achieve the same goal using db.Select(). It even provides a better way of handling queries with the IN clause, as explained in the Features section above.

sqlc

sqlc’s previously mentioned ability to generate type-safe code is another benefit for ease of use, as it reduces the amount of Go code you need to write for your database operations, saving you time and effort.

With an active and growing community of over 6,800 stars, sqlc also boasts strong engagement and community support.

The documentation provides a step-by-step walkthrough from installation to the generation of code, and there are also concise video tutorials if you’d like a more interactive approach. So, getting started with sqlc couldn’t be easier, as you’ll see for yourself below.

After installing the binary, write your config file in sqlc.yaml, which should look like the snippet below:

version: 1
packages:
  - path: "./"
    name: "main"
    engine: "mysql"
    schema: "schema.sql"
    queries: "query.sql"

Now all you need to do is write your plain old SQL in 2 files, just as in the image below, and run the command sqlc generate in your working directory:

The following list explains the elements of the above image:

  • The red box shows 3 new generated files: models.go for structs, query.sql.go, and db.go for other database-related code.
  • The yellow box highlights the schema.sql file containing your schema definition.
  • The blue box highlights the query.sql file, which contains all the SQL statements for your application’s database operations along with some metadata for generating the functions.
  • The green box highlights the run that sqlc generated in the working directory in the terminal.

Now, you only need to provide a database connection using the database/sql package, then call your required methods without modifying the generated code, as you can see in the following snippet:

func main() {
    // Create a new database connection
    conn, err := sql.Open("mysql", "theuser:thepass@tcp(localhost:3306)/thedb?parseTime=true")
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("Connected!")
    db := New(conn)
    // Initialize record to be inserted
    newSt := addStudentParams{
        Fname:       "Leon",
        Lname:       "Ashling",
        DateOfBirth: time.Date(1994, time.August, 14, 23, 51, 42, 0, time.UTC),
        Email:       "lashling5@senate.gov",
        Gender:      "Male",
        Address:     "39 Kipling Pass",
    }
    // Insert the record
    sID, err := db.addStudent(context.Background(), newSt)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("addStudent id: %v \n", sID)
    // Fetch the records
    students, err := db.fetchStudents(context.Background())
    if err != nil {
        log.Println(err)
    }
    fmt.Printf("fetchStudents count: %v \n", len(students))
}

Provided you are good at writing your SQL statements, this package’s generation of type-safe code makes it a better option, especially if you have to interact with many schemas of varying types.

GORM

GORM has very comprehensive yet simple documentation and guides on getting started. Unfortunately, GORM takes more of a code-based approach to interacting with the database, meaning there’s a steep learning curve at the start.

Using the GORM syntax, you might spend a lot of time initially constructing code similar to your raw SQL queries. However, once you’re familiar with the syntax, you’ll have a clean codebase with rare interaction with raw SQL.

GORM is the second biggest Go database package (after database/sql) on GitHub, with over 30,400 stars, which means there should be no shortage of community support.

The following example demonstrates how GORM would be used to implement the same insert statement, and multiple records query as before:

func main() {
    // Open a database connection
    db, err := gorm.Open(mysql.Open("theuser:thepass@tcp(127.0.0.1:3306)/thedb?charset=utf8mb4&parseTime=True&loc=Local"))
    if  err != nil {
        log.Fatal(err)
    }
    fmt.Println("Connected!")
    // Initialize record to be inserted
    s := Student{
        Fname:       "Leon",
        Lname:       "Ashling",
        DateOfBirth: time.Date(1994, time.August, 14, 23, 51, 42, 0, time.UTC),
        Email:       "lashling5@senate.gov",
        Address:     "39 Kipling Pass",
        Gender:      "Male",
    }
    // Add student record and return the ID into the ID field
    db.Create(&s)
    fmt.Printf("addStudent id: %v \n", s.ID)
    // Select multiple records
    var students []Student
    db.Limit(10).Find(&students)
    fmt.Printf("fetchStudents count: %v \n", len(students))
}

As you can see in the above snippet, the code is relatively simple, with very few lines. Once you get past the steep initial learning curve, GORM is actually more efficient for writing queries than the other 3 options.

Performance and Speed

The performance and speed of database operations are crucial to the overall performance of data-centric applications. The most suitable database package is highly dependent on performance, especially if you’re developing a low-latency application.

This section compares the performance of all 4 database packages. To undertake this benchmark, a MySQL/MariaDB database was set up with 15,000 student records. Since most use cases for these packages are queries for fetching records, the benchmark captured the performance of all 4 packages fetching 1, 10, 100, 1000, 10,000, and 15,000 records and scanning them into structs:

================================== BENCHMARKING 1 RECORDS ======================================
goos: linux
goarch: amd64
pkg: github.com/rexfordnyrk/go-db-comparison/benchmarks
cpu: Intel(R) Core(TM) i7-8550U CPU @ 1.80GHz
Benchmark/Database/sql_limit:1_-8                   9054            124134 ns/op
Benchmark/Sqlx_limit:1_-8                           8914            138792 ns/op
Benchmark/Sqlc_limit:1_-8                           7954            147056 ns/op
Benchmark/GORM_limit:1_-8                          13388             89251 ns/op
=================================================================================================
================================== BENCHMARKING 10 RECORDS ======================================
Benchmark/Database/sql_limit:10_-8                  7576            157780 ns/op
Benchmark/Sqlx_limit:10_-8                          4384            260402 ns/op
Benchmark/Sqlc_limit:10_-8                          4183            256384 ns/op
Benchmark/GORM_limit:10_-8                          9466            136556 ns/op
=================================================================================================
================================== BENCHMARKING 100 RECORDS ======================================
Benchmark/Database/sql_limit:100_-8                 2521            427603 ns/op
Benchmark/Sqlx_limit:100_-8                         2139            497755 ns/op
Benchmark/Sqlc_limit:100_-8                         2838            456938 ns/op
Benchmark/GORM_limit:100_-8                         1896            563539 ns/op
=================================================================================================
================================== BENCHMARKING 1000 RECORDS ======================================
Benchmark/Database/sql_limit:1000_-8                 516           2201303 ns/op
Benchmark/Sqlx_limit:1000_-8                         445           2786983 ns/op
Benchmark/Sqlc_limit:1000_-8                         535           2313674 ns/op
Benchmark/GORM_limit:1000_-8                         315           4186201 ns/op
=================================================================================================
================================== BENCHMARKING 10000 RECORDS ======================================
Benchmark/Database/sql_limit:10000_-8                 51          21690323 ns/op
Benchmark/Sqlx_limit:10000_-8                         38          28458473 ns/op
Benchmark/Sqlc_limit:10000_-8                         55          21558300 ns/op
Benchmark/GORM_limit:10000_-8                         28          40463924 ns/op
=================================================================================================
================================== BENCHMARKING 15000 RECORDS ======================================
Benchmark/Database/sql_limit:15000_-8                 36          32048808 ns/op
Benchmark/Sqlx_limit:15000_-8                         28          41484578 ns/op
Benchmark/Sqlc_limit:15000_-8                         34          31680017 ns/op
Benchmark/GORM_limit:15000_-8                         20          59348697 ns/op
=================================================================================================
PASS
ok      github.com/rexfordnyrk/go-db-comparison/benchmarks      77.835s

For the purposes of uniformity and fairness, the benchmark was run on the same hardware. The test also ensured a similar code structure by placing each action in a separate function and measuring their performance individually.

There are many factors that influence the performance on a production server, so we typically use simple benchmarks to eliminate external factors as much as possible. While this benchmark uses a single select statement, we encourage you to modify the source code and try out more complex tests, such as using join queries and nested structs and fetching higher record sets to better simulate your own production environment. You can replicate this benchmark using the benchmarks code directory of this repo on GitHub.

Each result set consists of three columns:

  1. The name of the benchmark method that was run.
  2. The number of times the benchmark was run until a reliable time was generated.
  3. The time (in nanoseconds) it took each time the benchmark was executed.

For the first two tests of 1 and 10 records, GORM outperforms the rest of the libraries. However, it trails significantly as the record count increases. sqlx performs quite consistently in third place in terms of performance, better than GORM, but it usually lags shortly behind sqlc and database/sql when data size increases.

The database/sql and sqlc packages perform very well across all six cases in benchmarks. As the number of records fetched increases (to 10,000 and 15,000 records), sqlc proves to be slightly faster than database/sql.

Conclusion

While database/sql is the default Golang package, whether you should use it or not depends on your needs as a developer. In this article, you saw the advantages of each package.

GORM is the best package for you if you need advanced querying, full support functions from underlying database technologies, and a clean codebase—as long as you’re willing to trade off some performance. If you only need basic queries and are comfortable writing your own SQL, then the database/sql or sqlx packages will do just fine.

Finally, sqlc is best suited for backend developers who work extensively with databases and need to write lots of queries under tight deadlines. You can write your raw SQL queries and generate code without having to worry about types, scanning, or other obstacles to productivity. sqlc also provides great performance gains compared to the rest, especially when dealing with greater volumes of data or record sets.

Note that this article has been updated due to an error in benchmarking. Many thanks to Lukáš Zapletal, who commented on the original article with a fix for the bug. Thank you as well to the JetBrains community for providing spaces like this that are designed for learning and contributing together.

]]>
What’s Next: GoLand Roadmap 2023.2 https://blog.jetbrains.com/go/2023/04/19/roadmap-2023-2/ Wed, 19 Apr 2023 11:39:18 +0000 https://blog.jetbrains.com/wp-content/uploads/2023/04/go-roadmap-blog-featured-image-1280x600-1.png https://blog.jetbrains.com/?post_type=go&p=343295 At the beginning of April, we released GoLand 2023.1

If you haven’t had a chance to check it out, here’s a brief overview: 

GoLand 2023.1 introduces the vulnerability checker, better navigation in gRPC code, and the Rename refactoring for generic receivers.

Interface implementations are now shown in the editor with Code Vision.

You can now run scratch files with non-standard-library packages, use regular expressions to create your own search and replace inspections, and quickly convert raw string literals to double-quoted ones and vice versa. The Implement interface intention action now works for unexported interfaces.

You will also find several improvements to the new UI, updates for Docker and Kubernetes, and additional enhancements for web development.

You can read more about the new features on the What’s New page.

If you prefer an interactive approach to learning about the new functionality, check out the What’s New in GoLand 2023.1 tutorial, which can be accessed from the Welcome screen.

Download GoLand 2023.1

The team really enjoyed working on this release. But we didn’t do it alone. Many users helped us improve GoLand by sharing their feedback and suggesting improvements, and we’d like to shout out to them here. You rock!

These authors provided the most valuable contributions to the 2023.1 EAP:

  • Nazar Pysko (nazarpysko)
  • Notealot Yu (714804968)
  • Eric Ye (trghoer)

Thanks a lot – your time and effort are greatly appreciated! We will contact you shortly to offer a 1-year GoLand subscription and a branded T-shirt.

As usual, after releasing a major version, we’d like to share our plans for the next one.

GoLand 2023.2: What’s coming next?

Please note: We can’t guarantee that all of the features listed below will be included in GoLand 2023.2.

We plan to focus on two main areas: user experience and error handling.

UX

In the user experience area, we’d like to implement several solutions and fixes. We hope these improvements will make using GoLand more enjoyable for you:

  • Migration from VS Code. We will bundle the VS Code keymap and add a VS Code migration dialog to the Welcome screen.
  • go mod download. To download Go modules in a project in GoLand, right now you need to apply a quick-fix. Some users want GoLand to run go mod download automatically. The discussion about which approach is better has continued for some time. In v2023.2, we will implement a solution allowing users to turn the automatic download of modules on and off.
  • GOPATH. The “GOPATH is empty” notification may confuse some users (mostly new ones). As of Go 1.18, you don’t need to set GOPATH manually because it is set to ~/go by default. But “GOPATH is empty” is still shown in GoLand for users who didn’t configure GOPATH explicitly, didn’t set the corresponding environment variable, and don’t have a ~/go directory. We will clarify this warning. 
  • Vendoring. Currently, vendoring is enabled in GoLand, depending on the language version. It’s not convenient in some cases – for instance when you have a monorepo containing the vendor folder used by another language, you might want to ignore it. We will allow disabling vendoring for such cases.
  • The Structure tool window. Sometimes users want the Structure tool window to show only the methods inside the file and not in the whole package. This is especially relevant in big projects where a type can have dozens of fields and methods. We will provide an option to show only the symbols in a file.
  • Find Usages. The Find Usages popup will show package names, so that you will be able to tell apart identically named files in different packages.
  • Debugger. We will implement a solution for showing a long string value in the View popup.

Errors

Error handling remains a challenge for Go developers. The Go survey states, “Following the release of generics, respondents’ top challenge when working with Go shifted to error handling.”

In the next version, we will work on some improvements in this area:

  • We will support multiple errors – a feature introduced in Go 1.20. 
  • errors.As and errors.Is will be supported.
  • We will also implement a solution for hiding error-handling blocks. 

Intention previews

We’ve enabled the preview of intentions and quick-fixes by default in 2022.3. We’re implementing support for all the cases gradually.

Profiling Go programs

Go 1.20 supports collecting code coverage profiles for programs, not just tests. This will allow us to implement support for profiling Go programs in GoLand. 

If you’d like to report a bug or suggest a feature, we are always happy to hear from you! Send us your feature requests via our bug tracker or tweet us @GoLandIDE.

]]>
Catching Up With Kat Zien on the Structure of Go Apps in 2023 https://blog.jetbrains.com/go/2023/04/11/catching-up-with-kat-zien-on-the-structure-of-go-apps-in-2023/ Tue, 11 Apr 2023 12:46:23 +0000 https://blog.jetbrains.com/wp-content/uploads/2023/03/Blog_Featured_image_1280x600-15.png https://blog.jetbrains.com/?post_type=go&p=335971 Let’s say I was asked to build a Go application for a website that hosts raffles.

I might end up with a file structure that looks like this:

├── main.go
├── api
│ ├── client.go
│ ├── raffle.go
│ └── user.go
├── database
│ ├── client.go
│ ├── raffle.go
│ └── user.go
├── Dockerfile
├── Makefile
├── go.mod
├── go.sum

But is this correct? Or is everything I’ve written here completely wrong?

This was a common feeling among Go developers back when Kat Zien gave her 2018 GopherCon US talk How Do You Structure Your Go Apps, a brilliant primer on the subject that has been referenced many times across multiple articles covering similar subjects.

I was curious to see if anything had changed 5 years on, so I invited Kat along for an interview.

portrait picture of kat zien

Kat Zien works at Monzo as a senior backend engineer and tech lead on the Operations team. Her main interests include automating #allthethings, sorting out legacy code and making things simpler and faster. She was co-organising PHP South West and London Gophers. Kat loves travelling and keeping active, appreciates good coffee and is a big Lego fan. She cycles across Europe with TechBikers to raise money for Room To Read.

This article will feature a summation of our discussion. If you’re reading and expecting an in-depth tutorial on how to structure a Go application, this is not the right place. I’ll take no offense if you bow out here.

If you’re completely unversed in this topic, I’d recommend watching Kat’s talk and then coming back, as I view this more as a commentary featuring the author.

All Good? Good. Let’s Get Go-ing!

A case for flat structures in single and multi-file applications

Single file example

├── main.go

Multi-file example

├── main.go
├── client.go
├── raffle.go
├── database.go

Surely this is too simple, right? Is there ever a case where you’d only want to use main.go? Especially in a professional environment?

Kat disagreed. A beginner trap is feeling the need to copy what some of the bigger and more complicated services are doing off the bat. However, doing so only serves to make your own code more complicated than it needs to be.

Plus, as a beginner, starting with a single file structure and then working towards grouping code into other files is a good way to practice and get used to understanding when it’s appropriate to separate code out.

“As simple as possible, but no simpler,” is a quote attributed to Albert Einstein, used by Kat in her 2018 talk. Over the years, that’s the mindset that Kat has continued to reaffirm whenever she builds services.

Kat mentioned that for several Advent of Code challenges, she only needed main.go and a few extra files. For the occasional simple project, why add on a more complicated boilerplate?

Structuring your packages: Updates on thoughts and trends

In this next section, I asked Kat about a few different structural trends that were within her original video and some that have emerged since.

Using cmd folders

cmd folder

├── cmd
│ └── main.go
├── api
│ ├── client.go
│ ├── raffle.go
│ └── user.go
├── database
│ ├── client.go
│ ├── raffle.go
│ └── user.go

Back in 2018, this was an emerging trend that you may still see today. The idea was to put any main.go files in the cmd folder and all packages in the pkg folder.

I was aware of this idea, but hadn’t really thought about where I’d picked it up from or why it appeared in the first place.

Essentially, the cmd folder is where you’d put different ways to launch your application.

However, nowadays, Kat feels cmd doesn’t really add any value, so you shouldn’t add it by default. She posed the question, “How often do you need multiple main.go files?” In Kat’s day-to-day, she typically only needs one.

If you specifically need multiple main.go files, then use the cmd directory; otherwise, is it necessary?

cmd removed

├── main.go
├── api
│ ├── client.go
│ ├── raffle.go
│ └── user.go
│ database
│ ├── client.go
│ ├── raffle.go
│ └── user.go

Internal and external package directories

Example of internal and external packages

├── cmd
│ └── main.go
├── internal
│ ├── api
│ │ └── client.go
├── pkg (external)
│ └──protos.go

An internal directory showcases to anyone looking at your service that this code is private. External services should not import any packages within this directory.

The pkg directory in this case contains packages that external services can import.

Kat’s opinion was that using internal directories isn’t always necessary. At her current place of work, everything is “internal” by default. In fact, they have a specific proto package which is used to allow for service-to-service communication. This effectively achieves internal and external separation without using those names within the repository.

However, aspects such as this are on a company-to-company basis. If your company goes forward with using an internal directory, there could be the argument that there really isn’t anything stopping someone from using those packages – unless it’s enforced either through an automated check or some other means.

For me, I don’t mind having a directory where I essentially put all my packages, provided the root directory contains other folders that are not Go packages.

├── main.go
├── internal
│ ├── api
│ │ └── client.go
├── config
│ └──creds.yml

In the above example, the config directory doesn’t have a Go file. So, if I was scanning the repository, I might think there is a config Go package if the internal directory didn’t exist.

It’s quite a minor thing, but again there are many ways to paint a cat.

A brief note on hexagonal architecture

If you ended up watching Kat’s talk before landing here, there’s one small regret she had with the final presentation. Back then, Kat didn’t marshal between layers.

├── main.go
├── api
│ └── client.go
├── domain
│ ├── raffle.go
│ └── user.go
├── database
│ └── client.go

Using my example, instead of the api package having its own user and raffle types, it would use the types from the domain package instead.

This would still follow hexagonal architecture, as the ‘core’ package – in this case the domain package – wouldn’t be using anything from the api package. It would only work the other way around.

However, Kat believes that although it’s likely fine for small apps, for larger applications it might be necessary to introduce marshalling between the layers of the hexagon, and the original example in her talk should have shown that.

For example, your api layer’s representation of something might differ from the domain representation of the same thing. You could have a domain object use a string to represent something, and the api layer could instead use bytes to represent the same thing.

├── main.go
├── api
│ ├── client.go
│ ├── raffle.go
│ └── user.go
├── domain
│ ├── raffle.go
│ └── user.go
├── database
│ └── client.go

That’s all folks!

Thank you, Kat, for your time and the chat!

To the readers, thank you for your attention. I’d love to hear your thoughts and how your opinions may have changed over the years.

If you want a more in-depth look into Go application structures from the voice of Kat herself, please check out her app-structure-examples repository.

Kat made this repository (almost immediately) after our interview to showcase some examples of the project structures she mentioned in her talk using a recent Advent of Code of challenge.

It includes additional commentary on each example and an FAQ section!

Teeny tiny final thing

I found another really cool repository while I was working on this article and wanted to share it with you. It was really interesting to explore, and I’d highly recommend giving it a look!

https://github.com/golang-standards/project-layout

I found it funny how in the Readme, it states, “If you are trying to learn Go or if you are building a proof of concept or a simple project for yourself this project layout is an overkill. Start with something really simple instead (a single main.go file and go.mod is more than enough).”

This is essentially how my chat with Kat started. Perhaps this view is the new trend, or perhaps that’s how the trend has always been?

Anywho, have a cool day!

]]>
GoLand 2023.1 Is Out! https://blog.jetbrains.com/go/2023/04/03/goland-2023-1/ Mon, 03 Apr 2023 16:25:56 +0000 https://blog.jetbrains.com/wp-content/uploads/2023/03/Release_Preview_image_1280x600_GoLand-2x.png https://blog.jetbrains.com/?post_type=go&p=336872 The next major version of GoLand is here! 

GoLand 2023.1 introduces the vulnerability checker and better navigation across gRPC code, and it makes the Rename refactoring available for generic receivers.

Interface implementations are now shown in the editor with Code Vision.

You can now run scratch files with non-standard-library packages, use regular expressions to create your own search and replace inspections, and quickly convert raw string literals to double-quoted ones and vice versa. The Implement interface intention action now works for unexported interfaces.

GoLand also provides the new functionality available in DataGrip and WebStorm, our IDEs for working with databases and web development, respectively. Check out the DataGrip 2023.1 What’s New and WebStorm 2023.1 What’s New web pages for more information.

To learn more about the new features and improvements in GoLand 2023.1, head over to our What’s New page, where you’ll find a full overview of the release along with helpful GIFs and screenshots.

Download GoLand 2023.1

If you prefer an interactive approach to learning, we invite you to complete the What’s New in GoLand 2023.1 tutorial from the IDE’s Welcome screen.

Let’s take a closer look at the latest and greatest in GoLand!

Vulnerability checker

  • GoLand can now highlight packages with known vulnerabilities in go.mod.
  • There is a quick-fix to update a dependency to a version that doesn’t have vulnerabilities.
  • GoLand also highlights method calls from packages with known vulnerabilities right in your editor. 
  • More information about known vulnerabilities is also available in the new Dependency Checker tool window.

gRPC navigation

You can now navigate and access declarations of messages, services, and methods from Go code and their Go implementations from .proto files.

Scratch files

You can now run scratch files with non-standard-library Go dependencies.

Rename for generic receivers

When you rename a type parameter in a struct, the Rename refactoring now suggests changing the receivers accordingly.

Intentions and quick-fixes

  • We have a new intention action that lets you quickly convert raw string literals – strings that are surrounded by backticks – to double-quoted ones, and vice versa.
  • We’ve simplified the conversion of integers to strings: You can now do so with just 1 quick-fix, not 2 as before.
  • The Implement interface intention action now works for unexported interfaces.
  • GoLand now has an inspection and a quick-fix to help you detect and remove leading spaces in Go directives, like //go:embed.
  • It is now possible to preview a broader range of intention actions and quick-fixes.

Performance improvements

  • We’ve improved the IDE startup experience by performing the Scanning files to index process in smart mode.
  • GoLand now suggests adding specific folders to Microsoft Defender’s list of exclusions.

Editor

  • We’ve updated the Code Vision feature so that GoLand now shows the number of implementations for an interface and its method specifications.
  • You can now use regular expressions to create your own search and replace inspections.
  • Shared URLs in GoLand’s Go Playground integration now include the version parameter if you choose the dev or previous versions. You can also disable the popup window that asks for your permission to share code in the Playground.
  • There’s now a special setting that allows you to control the placement of pasted content.
  • A new setting allows you to configure the IDE to show whitespaces as small dots only when you select code.
  • We’ve updated the Typo inspection so that it no longer checks the spelling of hashes and special values and doesn’t report them as misspelled.
  • We’ve introduced a new Find Usages group for function calls – the Call group.

User experience

  • It’s now possible to zoom into and out of GoLand entirely, increasing or decreasing the size of all UI elements at once.
  • We’ve introduced a new layout option that allows you to unify the width of the side tool windows or retain the ability to freely adjust their sizes as you customize your layout.
  • You can now save and manage several tool window layouts and switch between them when needed.
  • This version adds an option to predefine the behavior of Actions on Save for new projects.

The new UI

Last year, we introduced a new, more minimalist UI for GoLand and other JetBrains IDEs. We’ve been listening to your feedback and refining the new UI accordingly. Read about the key changes that have landed in this release, and try it out if you haven’t already by ticking the New UI checkbox in Settings/Preferences | Appearance & Behavior.

  • To improve your user experience with the new UI on smaller screens, we’ve introduced Compact Mode, which provides a more consolidated look and feel.
  • We’ve introduced the option to vertically split the tool window area.
  • When you have several projects open on macOS, you can now easily switch between them using project tabs displayed under the main toolbar.
  • We’ve added the Show Hidden Tabs feature in the new UI.
  • We’ve fine-tuned the user experience of the new UI by adding a pane that displays the name of the file that is currently open when editor tabs are hidden.
  • We’ve redesigned the Run widget at the top of the IDE window.

Docker

  • We’ve added completion for container names when you use the testcontainers-go package.
  • The Dashboard tab of the Docker-compose node now pulls together logs from every Docker Compose container and displays them all in one place, updated in real time.
  • You can now easily connect to Azure Container Registry.
  • Now you can add :z configuration flags to Docker bind mounts, which allows you to connect volumes to Docker containers on SELinux workstations.

Kubernetes plugin

  • We’ve added a new action – Kubernetes Resource – to the New menu that appears when you right-click in the Project tool window.
  • We’ve introduced a new dialog to create Kubernetes Secrets.
  • When you use the View YAML action for resources from a cluster and make any changes in the opened file, GoLand now highlights all of your edits with color-coded marks in the gutter.
  • Additionally, by using the Compare with Cluster icon, you can open a full diff view that will fetch the resource’s current version from the cluster and compare it with the local version.
  • You can now easily access a kubeconfig file in the Services view and open it in the editor.
  • You can now assign shortcuts for most Kubernetes actions in the Service view.

Markdown

  • A new intention action allows you to correct the formatting of tables.
  • The Fill Paragraph editor action is now supported for Markdown files.
  • We’ve added a dedicated page for configuring and editing your Markdown preferences in Settings/Preferences | Editor | General | Smart Keys.

Version control

  • Navigating between branches is now easier, as they are grouped and stored in expandable lists.
  • We’ve implemented completion in the Create New Branch popup.
  • To make tracking changes to files easier, we’ve added color hints to the Structure tool window.
  • Background commit checks are now performed in the background after you commit but before you push.
  • We’ve reworked the Pull Request tool window.

Web development

  • Astro support is now available.
  • GoLand will now automatically transform your single- or double-quoted strings into template literals whenever you type ${.
  • We’ve added TypeScript support in Vue templates when you set the lang attribute in a script tag to ts.

That’s it! Please tell us what you think about our new features! Leave your comments here, report any issues you encounter to our bug tracker, ping us on Twitter, or drop us a message in the Gophers Slack #goland channel.

]]>
GoLand 2023.1 Release Candidate Is Out! https://blog.jetbrains.com/go/2023/03/24/goland-2023-1-release-candidate-is-out/ Fri, 24 Mar 2023 16:38:26 +0000 https://blog.jetbrains.com/wp-content/uploads/2023/03/Blog_Featured_image_1280x600_GoLand-2x.png https://blog.jetbrains.com/?post_type=go&p=336092 GoLand 2023.1 Release Candidate is now available.

Please note that to use GoLand 2023.1 RC, you need to have an active subscription or start a 30-day trial.

In this build, we have fixed some bugs. We’ve also updated the Code Vision feature. 

Please read this Beta 2 blog post if you want to find out more about all the features that are coming in 2023.1.

Code Vision: Interfaces implementations

GoLand now shows the number of implementations for an interface and its method specifications.

In the previous version, we introduced usages displayed near all functions and types showing how often the function or type is referenced in the current project. Also, the code authors are displayed if version control integration is enabled.

That’s it for today! Let us know what you think about this release. You can share your feedback with us here in the comments, on Twitter, in our bug tracker, or in the Gophers Slack #goland channel.

]]>
GoLand 2023.1 Beta 2 Is Out! https://blog.jetbrains.com/go/2023/03/10/goland-2023-1-beta2/ Fri, 10 Mar 2023 14:47:58 +0000 https://blog.jetbrains.com/wp-content/uploads/2023/03/Beta_Preview_image_1280x600_GoLand-2x.png https://blog.jetbrains.com/?post_type=go&p=331993 GoLand 2023.1 has reached Beta 2! This is the last build in our EAP cycle that doesn’t require a license.

You can get the Beta 2 build via the Toolbox App, download it from our website, use a snap package (for Ubuntu), or from inside GoLand, select Check IDE updates for: Early Access Program in Settings | Appearance & Behavior | System Settings | Updates

Download GoLand 2023.1 Beta 2

The Beta 2 version provides all of the new features and improvements that have already been announced during our current EAP cycle and are expected in the major 2023.1 release. To read about these updates in detail, refer to our EAP blog posts. Here are some of the highlights:

Let’s take a look at the new features in this Beta 2 build.

Update vulnerable dependencies to the safe version

In the previous Beta build, we announced our new Vulnerability checker. GoLand can now highlight packages with known vulnerabilities in go.mod and method calls from packages with known vulnerabilities.

There are additions to that feature in GoLand Beta 2. You can place the cursor on a highlighted package in go.mod, press Alt+Enter (⌥ ↩), and choose the Change <package name> version to <version> quick-fix to update a dependency to a version that doesn’t have vulnerabilities.

Completion for testcontainers-go

testcontainers-go is a Go package that allows you to create and clean up container-based dependencies for automated tests.

In this build, we’ve added completion for container names when you use the testcontainers-go package.

After typing in the container name, you can use the Pull Docker image action that was implemented earlier.

gRPC navigation

GoLand’s HTTP Client currently supports running gRPC requests. You can also run gRPC requests from the Endpoints tool window.

This version offers another useful addition to our gRPC feature set. You can now navigate and access declarations of messages, services, and methods from Go code and their Go implementations from .proto files.

For this, press the dedicated icon next to a declaration of a message, service, or method, or their implementation.

Save multiple tool window layouts

You can now save and manage several tool window layouts and switch between them when needed.

To save a new layout, arrange the tool windows as desired and go to Window | Layouts | Save Current Layout as New. Once you adjust the arrangement, you can either update the currently used setup using the Save Changes in Current Layout option or save these changes for another custom layout. To activate a saved layout, find it in the list in Window | Layouts, hover over its name, and hit Apply.

 
That’s it for today! We’d love to hear what you think about the new features. Get in touch with us on Twitter, leave your comments here, open an issue in our tracker, or drop us a message in the Gophers Slack #goland channel. Thanks!

]]>