Talks
Google Go for Ruby Hackers
Summarized using AI

Google Go for Ruby Hackers

by Eleanor McHugh

In the video 'Google Go for Ruby Hackers,' presented by Eleanor McHugh at LoneStarRuby Conf 2011, the speaker explores the Go programming language from the perspective of Ruby developers. The session highlights the similarities and differences between the two languages while providing insights into Go's features.

Key points discussed include:
- Language Comparison: McHugh emphasizes Go's statically-compiled nature compared to Ruby's interpreted style, pointing out shared features such as garbage collection and dynamic typing.
- Simplicity of Syntax: The presentation covers Go's minimalist design with a limited set of keywords and basic types, contrasting this with Ruby's more dynamic type system.
- Types and Functions: Basic types, constants, and the static nature of Go's type system are examined, alongside examples of class definitions in Ruby to illustrate the differences in inheritance and type management.
- Custom Types and Interfaces: The concept of defining custom types and using interfaces in Go is introduced, explaining how types can be combined or embedded for functionality.
- Testing and Benchmarking: McHugh emphasizes the integrated testing framework ('go test') in Go and how it facilitates performance measurement through benchmarks.
- Reflection and Concurrency: The use of reflection for dynamic type interpretation and Go's approach to concurrency using go routines and channels is discussed, showcasing how they enhance performance. These routines operate with minimal memory, allowing thousands to run concurrently.
- Conclusion and Resources: The talk ends with recommendations for further learning on Go, including visiting the Go web homepage and exploring additional presentation slides for comprehensive understanding.

Overall, McHugh aims to equip Ruby developers with a foundational understanding of Go, encouraging them to delve into its static type system and explore concurrent programming capabilities. The takeaway from the session is that understanding Go can broaden a developer's programming toolkit and help improve application performance through effective concurrency models.

00:00:06.319 Good morning! Am I good to go? Yes? Great!
00:00:19.680 I can't hear anyone, so this is a bit different for me. Can you hear me? Okay, so you're only going to hear me. I'll repeat questions, and I'll be around after this session. I’ll be available on IRC and Google Plus if anybody has any serious questions that need a long answer.
00:01:00.800 Good morning, Austin! My name is Ellie, and I’m mostly known for doing some interesting things with Ruby. Today, I’m here to talk about my current obsession: doing some fun stuff with Go.
00:01:11.520 This will be a fast-paced presentation. I'll try to teach you the entirety of Go in 3 minutes and 40 seconds. I did a similar presentation at RubyConf last year as a lightning talk.
00:01:18.560 Today, I'm aiming for something a little clearer, but I apologize in advance since it's a very large slide set. The slides will be available on SlideShare later, and they should all make perfect sense. So, without further ado, let's dive into Google Go.
00:01:37.280 First, we often think that Go is a statically-compiled language, so it must be very different from Ruby and more like C or Java. However, Go and Ruby share a number of similarities. They have very different compilation models—Ruby is interpreted, but both languages utilize garbage collection and strong typing. They both also feature a dynamic type system.
00:02:24.640 Let's start by looking at Go's minimalist design. This slide shows every single keyword in the Go language. These keywords are crucial for organizing files, declaring types, and controlling basic program flow. You’ll encounter all of them throughout this presentation.
00:03:07.040 For a low-level language, Go has a reasonably small number of types. It includes several numeric types, but mainly consists of value types, which are immutable, and reference types, which are mutable. I refer to the latter as 'invocation types' due to my dislike for using the word 'function' twice in the same context. However, Go does feature proper closures and methods that are bound to types.
00:03:38.319 Let’s examine a very simple Go program. It includes a main function that resides in a main package. It also contains an import statement, allowing it to load components from other packages. Here’s how Go defines its elements.
00:04:02.959 Constants and variables are straightforward in Go, but I'm going to start by explaining how types work in Ruby in a somewhat inaccurate but useful manner. To truly grasp the similarities between Go and Ruby, we need to delve into type systems. I’ll be using code examples and diagrams that should help clarify things.
00:04:50.720 Here’s a simple Ruby example with a class called 'Counter' and a subclass called 'DoubleCounter' that inherits from it. In a Ruby program, an instance class defines the actual object you’re manipulating. The 'DoubleCounter' is an instance class that can inherit behaviors from 'Counter' in an inheritance hierarchy.
00:05:55.840 Are we going to get a click-through? Great! In this example, 'Counter' is inherited by 'DoubleCounter'. From these two classes, a concrete type emerges, representing the type of the current object in use. While we don’t often think about typing in Ruby, it serves as a helpful point of comparison with Go.
00:06:38.400 In Ruby, you send a message to an instance, and along with the action or data manipulation you were looking for, you also get confirmation that a type has been asserted. This is significant because Ruby does not focus on type assertion. In contrast, Go revolves around type assertion, which we will see demonstrated later.
00:07:12.960 A couple of years ago, I engaged in a debate on Ruby Core with a fellow who argued for more static typing in Ruby. I concluded that Ruby is akin to quantum mechanics in programming languages: everything can change behind your back without your noticing. This ambiguous type system can be frustrating for computer scientists.
00:08:00.480 I come from an embedded systems background, so I appreciate the need for both static and dynamic programming. I have had countless discussions about features that Ruby programmers take for granted, much to the dismay of computer scientists who prefer traditional static types.
00:08:55.680 Typing in Go is markedly different from typing in Ruby, C++, or Java. Here’s a simple example of defining your own custom type in Go. Go includes primitive types, but you can adapt them to create custom-defined types, equipped with their own methods.
00:09:38.320 From the combination of the memory layout and method set, you get a static type. Thus far, we haven’t seen anything that would make a Java or C++ developer feel uncomfortable. This illustrates the description of a type in code.
00:10:06.720 Now, things get more interesting. I'm defining a type called 'Buffer', which has a memory layout composed of a slice—essentially a window on an array—where all elements of that slice are of a user-defined type called 'Int'. This method set goes along with that definition. Here is an example of using this program. This is where we select the 'Buffer' type from the package 'Integer'.
00:11:03.200 We can instantiate this 'Buffer' type since we can already do it with a slice. The example provides a standard reference to an item in a slice and invokes a method on it. Practically, we would typically import the whole integer namespace into our current scope, making our code easier to read.
00:11:27.679 Next, we have another type called 'Vector', which is structured to contain a 'Buffer' type. Unlike the previous example, this does not reuse the same memory layout; it establishes a distinct data structure by embedding this type. This is as close to inheritance as Go gets.
00:12:02.320 In this scenario, 'Vector' can access all the functionalities of 'Buffer', but it can't alter the 'Buffer' embedded within it. I may expand on this point later as it is intricate, but for now, this explains how type embedding works.
00:12:35.920 This establishes a type model in Go: whenever we define a type, we associate a memory layout and a method set with it. The overall static type system in Go is quite robust, and by this point, C++ programmers would likely be impressed, although they might lament the absence of proper inheritance.
00:13:17.680 Interfaces in Go define a set of methods, akin to how sending a message to an object in Ruby verifies whether that object is capable of responding to that message. The difference in Go is that all this information is stored statically at runtime, enabling type inference to verify how an object conforms to a specific interface.
00:14:10.560 Now, let’s examine the 'Blank Interface'. This refers to any type, regardless of its method set, meaning it also encompasses all built-in intrinsic types. In this example, we showcase a type that implements an interface by simply defining the required methods. These methods can reside in completely different packages.
00:15:21.160 Moving on, we can illustrate a unique trick here. In Go, we have the ability to create zero values for different types. For example, when creating a pointer to a zero value for an integer, we observe that everything in Go is assigned a zero value upon creation. This simplifies many of the concerns we face when working with initialization in certain programming situations.
00:16:09.440 This snippet shows that another type can also implement the interface, provided we've defined the respective methods. However, in this case, 'IAdder' implements an interface that includes 'Increment', meaning it can be utilized in contexts where increment functionality is needed.
00:17:03.680 Let’s observe an example that highlights testing in Go. Testing is inherently integrated into the language. I want to present a bit of code that I will incorporate into this buffer type, which will aid in writing tests. Here, we define a variable of an interface type, which is utilized internally with two pieces of information.
00:17:40.480 This process is akin to how the V8 JavaScript runtime operates. The internal storage contains a 32-bit field acting as a type specifier and another 32-bit field that references the type itself. Down below, we can assign different types that comply with the interface, enabling us to effectively make use of successfully defined methods.
00:18:35.440 It’s worth noting that we reference type assertion here. When specifying the interface for 'Result', I intentionally avoided clarifying what content is passed back from the method. The actual assertion can clarify this, allowing for further type filtering in line.
00:19:29.920 Let's shift gears and explore the distinct advantages of Go. Unlike Ruby, an object in Go possesses a known static type, fixed at compile time. All types are determined at link time because Go is fully statically linked. This is both a benefit and a drawback, depending on your use case.
00:20:07.040 In Go, you cannot create new types on the fly, which I sometimes find frustrating as I often do so in Ruby to streamline my code. Instead, Go renders a more fixed—even conducive—environment for programming, assuring that many common errors are eliminated.
00:20:54.080 Testing in Go is built-in and utilizes a package called 'testing', which is part of a larger tool known as 'go test'. Consequently, all Go programs are structured with a makefile that seeks for files containing '_test'. Any functions within those files that have names starting with 'Test' will be executed as tests.
00:21:57.120 My practice is to import testing packages into the package I aim to test, which permits internal tests. Not doing this means I can't access certain private functions or variables, making some tests more straightforward.
00:22:47.680 This code sample showcases how to instantiate vector values and utilizes Go's switch statement—a feature that distinguishes itself from C's implementation. Go's switch executes all statements until it locates a successful case.
00:23:40.640 Each case only proceeds if it passes conditions; otherwise, the code isn’t executed. This aspect differentiates it from conventional programming languages. We’ll skip through further iterations of examples as they are largely redundant.
00:24:34.080 In addition to testing, Go test supports benchmarking natively. It performs benchmarking by offering benchmark functions. A peculiar idiom is used to measure the time taken for these functions, helping developers understand underlying performance.
00:25:14.480 The key variable, 'b.n', runs the loop with that set to one, determining the base time for the operation. Once established, it will run again with this limit to ascertain the actual benchmark duration.
00:25:58.560 Now let’s delve into reflection in Go, a subject closely tied to the majority of this talk. Reflection specifies how to conduct distributed MapReduce tasks, which is principally a method to demonstrate concurrency.
00:26:45.440 Reflection is generated via the 'reflect' package. All instances where I relay information regarding a type can be examined by using reflection to better understand how it constructs dynamic types.
00:27:49.440 Here’s also where we can venture into the intricacies of Go. I emphasize that this approach allows for flexibility when programming by defining how we interpret types and functions, specifically when they get much more complicated.
00:28:56.640 In Go, as with several other languages, we can make effective use of channels to orchestrate concurrency. The design permits one-way and two-way channels, and while I generally simplify them, specifying them is not inherently included within their type.
00:29:53.680 To create a synchronous channel, we can do so without allocating buffer space. The difference between synchronous and asynchronous channels depends solely on buffer presence, which is an interesting design choice.
00:30:49.440 Now, let's look at how to initiate a go routine. These routines run independently in parallel, with distinct advantages. They operate on a much smaller stack size compared to threads in traditional programming languages, resulting in superior efficiency.
00:31:57.760 Go routines provide the means to allocate smaller images for lower memory consumption with a notable ability to grow dynamically. Consequently, numerous Go routines can occupy the same thread.
00:33:14.080 We can utilize them to run a function in parallel, thus accentuating how they benefit smooth and effective processes. However, it’s essential to be cautious of shared mutable states as I previously highlighted.
00:34:54.080 As we draw nearer to an end, there are additional examples demonstrating how to manipulate values across different functions. However, I will move quickly as we’re running out of time.
00:35:26.720 As we explore iterations, I want to underline how we can enhance Go's function capabilities by storing functions and applying them later. The creation of channels adds to the richness of concurrency within Go.
00:36:30.400 As I conclude the session, there are resources available for additional learning! I'd recommend visiting the Go web homepage for more information. You can find many engaging projects on GitHub, and I’d encourage exploring the 352 slides from this presentation for further insights.
00:37:40.960 If you have questions, feel free to reach out to me on IRC or Google Plus. Thank you all for joining!
Explore all talks recorded at LoneStarRuby Conf 2011
+15