Go Generics Revisited

Go Generics Revisited

First, I'll define critical in terms of programming language features/libraries: anything I can't reasonably write software without. In the last chapter, we discussed some of the benefits of generics:Type safetyEliminates the need to write repetitive, boilerplate codeReuses and shares code.

Critical

First, I'll define critical in terms of programming language features/libraries: anything I can't reasonably write software without. A lot of things I would call very beneficial, but very few things I would consider critical.

I would consider language features like some kind of parallelism to be very beneficial, but not critical. It's definitely less pleasant in a language like C to manage threads via an API, but there's always examples you can follow, you're not in a vacuum. The only things I would call critical in a language are stuff every general purpose language has anyway, such as control flow statements and grouping functions together (such as classes, modules, namespaces).

For libraries, I would consider an HTTP implementation, crypto functions, and database drivers to be critical. I just don't have time to waste reinventing these wheels, and I doubt my API would be so much better than what's been done already anyway. And if I did want to write some API around these ideas, I would just write it on top of the provided abstractions anyway, I definitely would not start from scratch.

Collections

I view a collection in a more abstract way than just what a language like Java calls collections: an aggregate that contains one or more objects with an API for accessing them, with some combination of reading, write, add, remove, and transform operations.

According to this view, sure, lists, sets, and maps are all collections. But so is an Optional - it is a collection of one value that may or may not exist, and the API is centered around performing transformations and access to the value safely without NPEs if the value does not exist.

A Stream is a collection of items with an API to queue up operations like transforms and filters, and ultimately producing a new value by iterating each element, performing the queued up operations on it, and collecting the results into a new value - which may be a whole new structure or just a single value.

When you write a Customer class that contains a List

, really you're writing a custom collection. It has some strings for the Customer's name parts and some more strings for the parts of each address. The only real difference between this custom collection and a general one is that it has labels - unlike a List, where each string has no special meaning, they're just a bucket of strings, the Customer offers labels like first name, middle name, and last name.

If you follow the Single Responsibility Principle, the Customer class should not be anything but a collection - it should only have getters and setters, and in Java, it would generally have custom hashCode, equals, and toString methods. Some of those getters and setters can be higher level: the Customer class could have getters/setters for specific address types (such as billing, mailing, and physical). These higher-level getters/setters would help to ensure you never have two addresses of the same type since that doesn't make sense.

So if the Customer class is just a custom collection, why bother with it at all? Why not just use ordinary generic collections?

  • Generic declarations such as "Map<String, Object>" convey no meaning.
  • Tools like ORMs and marshallers that convert objects to and from database rows and text formats would be unable to do one upfront analysis - every time they receive the map or list or set, they would do something like read the first item, analyze it, and assume the remaining elements are the same. They would definitely not perform as well.
  • Where do you put custom methods like the Customer getters and setters for different address types?
  • Generalized types do not provide any statement of intent - the type "Customer" immediately invokes real-world notions of a customer, someone who pays for a product. "Map<String, Object>" simply doesn't.

My point being I simply fail to see some great distinction between the terms aggregate and collection, just like I fail to see the great distinction between a small and midsize car.

Generic Declaration Versus Application

Generics are always split into two separate parts: the declaration of one or more expected generic types, and the application (or usage) of these generic types.

In Java's case, the declaration is NOT subject to type erasure - ONLY the application. This means that if you declare a Customer class with a field of type "List

", it is possible through reflection to determine that the field's generic type is "List
".

This allows frameworks to make analyses. An example is the JAXB framework - it can analyze the Customer class and determine what the xml element name is for Customer. It can also analyze the List

field and Address class to determine what xml element name to use for Address. It would naturally expect the Address elements to be children of the Customer element.

But to actually apply generics, there are only a few ways to do so:

  • Field types
  • Constructor/Method parameters and return types
  • Analysis

Sure, you can declare a generic type on your class, like the List interface declares List. But that isn't usually useful in and of itself - the usefulness comes in when you have fields and constructors/methods that do something with the generic type. In the case of List, it obviously stores and returns the generic type in some kind of iterable structure, like a two way linked set of nodes.

It is somewhat rare but possible to apply generics solely through analysis, using reflection. In some cases, you don't need generic methods or fields, you just need to examine things like superclass declarations. For example, if XDocumentParser extends DocumentParser, it is possible to examine the generic superclass of XDocumentParser to see it parses document type X, and maybe that is all you need to do to create a system that can parse different document formats with different parsers.

A specialization of analysis is runtime code generation, such as Spring data: you declare an interface that extends "Repository" and declares methods like "List findByLastNameOrderByFirstNameAsc(String firstName)", and Spring will generate an interface implementation at runtime. In this case, the application is the generation of implementation via Proxy. To generate code at runtime, Spring must determine what query to execute for the above method, and prepare some strategy for executing it when the method is called.

Once you understand that classes that describe data are really just custom collections and that generics can only be applied to fields, methods, and analysis, then you realize there are really only three major use cases for generics:

  • Collections
  • Utility methods (eg, in Java a static generic method)
  • Analysis/code generation

web dev go generic programming

Bootstrap 5 Complete Course with Examples

Bootstrap 5 Tutorial - Bootstrap 5 Crash Course for Beginners

Nest.JS Tutorial for Beginners

Hello Vue 3: A First Look at Vue 3 and the Composition API

Building a simple Applications with Vue 3

Deno Crash Course: Explore Deno and Create a full REST API with Deno

How to Build a Real-time Chat App with Deno and WebSockets

Convert HTML to Markdown Online

HTML entity encoder decoder Online

Ordered Maps for Go 2 (Using Generics)

In this tutorial, we’ll be learning the bare bone basics of Generics in Go 2. This feature will be a game-changer. We’ll be harnessing the power of Generics to create an OrderedMap type.

whatsapp web-w app web-webs whatsapp »

whatsapp web-w app web-webs whatsapp-web.whatsapp.com-wsp web-web.whatsapp.com qr-whats up online-whatsappwebsite

What's new in the go 1.15

Go announced Go 1.15 version on 11 Aug 2020. Highlighted updates and features include Substantial improvements to the Go linker, Improved allocation for small objects at high core counts, X.509 CommonName deprecation, GOPROXY supports skipping proxies that return errors, New embedded tzdata package, Several Core Library improvements and more.

Python vs Go for Web Development – A Comparison of the Programming Languages

Python has rapidly increased in popularity in recent years and is now one of the most widely used programming languages in the world. If you are considering using it for your next web development project, then you may also be aware of Python’s...

Build a Go Web API with the New Digital Ocean App Platform: A How-To Guide

Recently, Digital Ocean announced they're entering the PaaS market with their new application platform. They've hosted virtual machines (droplets) and Kubernetes based services for years, but now they're creating a platform that's a simple point and click to get an application up and running.