My Contribution to a Popular Open-Source Package Caused a Panic in Golang Projects
Tags: webdev, opensource, programming, github
Published: 2022-08-27 13:11:21

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fuipfnibupjdzo2n0clw.png)
 

Hello, today I will tell you how my development to a popular open-source project caused errors to people using the project around the world and what I learned from this process.

**Content**
— Swaggo Project
— Our Requirement and My Contribution
— The Problem
— Reason of The Problem
— Function Definition Withtout Body (go:linkname)
— The Solution
— Learned Lessons


---
### SWAGGO Project
![https://raw.githubusercontent.com/swaggo/swag/master/assets/swaggo.png](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ous9bluvnacyw6y6m9ss.png)
 
Creating swagger documents for your API projects developed in Go language is a little different from languages such as Java, C#. Generally, you can create it by adding Swagger directives in the comment lines of the code you write, and you don't have many alternatives for this.

The [swaggo/swag](https://github.com/swaggo/swag/) project is one of the most popular and widely used solutions.

The basic process of this project is creating the swagger document by browsing the Go files and processing the comment lines in the definitions. It does this by creating an [Abstract Syntax Tree (AST)](https://en.wikipedia.org/wiki/Abstract_syntax_tree) and navigating it.

---

### Our Requirements and My Contribution
While trying to create a swagger document for a project with my teammate, we realized that we could not make the definition we wanted using the [swaggo/swag](https://github.com/swaggo/swag/) tool.

What we wanted to do was to define the request and response objects inside the handler function we created and ensure that they can only be accessed from within the function. But when we did this, the [swaggo/swag](https://github.com/swaggo/swag/) parser package could not access the related request and response objects.

I wanted to make a contribution to the [swaggo/swag](https://github.com/swaggo/swag/) library in order to overcome this problem.

First of all, I opened an issue to the library and asked if we needed such a thing and that I wanted to contribute by making this development.
In response, they said that it is not possible to parse private definitions and when they asked how I would do it, they were curious about my proposal and were waiting to see it.

I rolled up my sleeves. I did the development at the first opportunity and opened PR for the project.

As a result of the development I made, request/response objects became definable within the function. 💪

{% embed https://github.com/swaggo/swag/pull/1283 %}

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u0hhb3f5gra7vuzdg1xw.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dsiexf63ctmd7s1mku3j.png)
  

---

### The Problem
It's a Friday evening... The work is over, there are minutes... I'm looking forward to the weekend... And... I got a message from my teammate that one of our projects got an error 😞

I actually want to share the full conversation:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v6hoh93m01awcynpblrw.png)

Translation:
- Vural: bro I will tell you something
- Me: yes bro
- Vural: one of our services getting error while generating swagger do, and guess what on which part :D
- Me: is that because of my development asdfasdf
- Vural: yes, I guess asdfsadfs
- Me: you can't be serious asdfasdf


We immediately went to the project's Github page and looked at the issues. And what we saw made me a little uneasy.

Many [swaggo/swag](https://github.com/swaggo/swag/) package users were experiencing errors and they were all getting errors in the CI/CD pipelines or while manually generating swagger due to my development.

{% embed https://github.com/swaggo/swag/issues/1309 %}

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6bafkncxnmcwc411t68o.png)
 

Frankly, I was surprised by this situation because I wrote unit tests for my development and the code was working correctly. In fact, the successful passing of the current unit tests proved that it did not break any previous development.

So what could be the problem? 🤔

---

### Reason of The Problem

I'm attaching a screenshot from my development for [swaggo/swag](https://github.com/swaggo/swag/).

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zv5dkgfa64d5sm0n64y9.png) 

As we can see in the error messages, the error is received in the `parseFunctionScopedTypesFromFile` method. In fact, the exact line number of the error is 168.

Now let's take a closer look at this method I wrote.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gksq74uu05y952gilgpj.png) 

In line 168, AST is visited and if there is **FunctionDecleration** among the definitions, what written inside the defined function is iterated with a for loop.

So if we are sure that a function definition exists, why do we get an error when trying to iterate this function definition with a for loop?
What causes the nil pointer error?

When we look at the `functionDeclaration.Body` variable, we see that it is a pointer type.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jixq9yc6opgoyvngjjq9.png) 

I didn't do a nil check here because I assumed that if a function was defined, that function would have a body definition.

But in reality it may not be so.👇

---

### Function Definition Without Body

Does this term sound foreign to you? Can we define a function without writing a body?

Consider the code below, do you think this code is a valid definition in Go?

Will we get an error if we try to run it?

{% embed https://gist.github.com/mstrYoda/29c8645b167bb635049b4d9062eb1c89
%}

Yes, as you guessed, we cannot run or even compile this code because it is not a valid definition.

Can we run the code below?

{% embed https://gist.github.com/mstrYoda/9fe554b3943a41fccb77cf4e680dbb45 %}

Here, unlike the previous one, the answer will be yes, we can run it.

A little-known feature of Go is that we can link a function definition to the function definitions of other packages with the `go:linkname` directive.

Thus, we can define a function without defining a body.

And if you have noticed, this feature allowed me to use a private function defined under the Go runtime package.

External dependencies that we use in our projects can have such function definitions. And when we tried to create a swagger document with the `swag --parseDependency` command, functions with this definition caused a panic in my development because it also parsed dependencies.

---

### The Solution
I was going to do a development to fix the problem right away, but the good thing about the open-source community is that another developer wrote the code that fixed the bug before me and created a PR.

{% embed https://github.com/swaggo/swag/pull/1310 %}

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kh736b2u9li52vdc5bi1.png)

---

### Learned Lessons
With this problem, I learned some lessons for myself.

✅ Never bypass the nil pointer check hypothetically
✅ Unit tests may not always be enough. Do the end to end test
✅ We can write functions without body definition using `go:linkname` with Go, we can import functions from private packages
✅ Never make the package dependencies the latest version, specify the version you are sure is working 

---

I hope it was a fun and useful content for you. Take care of yourself, I wish you bug-free codes 🙏

---

```
Let's Connect
```

[Twitter](https://twitter.com/mstrYoda_)
[Github](https://github.com/mstrYoda)


You can support me on Github: [Support mstrYoda on Github](https://github.com/sponsors/mstrYoda/)

[![Buy Me A Coffee](https://cdn.buymeacoffee.com/buttons/default-black.png)](https://www.buymeacoffee.com/mstrYoda)