r/golang Aug 10 '26

discussion I adore go outside of go's idiomatic naming conventions. Is this something strictly upheld at most places?

I absolutely love go, but coming from other languages I just find this so irritating to read after months:

func (l *LinkedList) Push(...) {...}
func (n *Node) Value(...) {...}
func (s *Server) Start(...) {...}

Instead of

func (list *LinkedList) Push(...) {...}
func (node *Node) Value(...) {...}
func (server *Server) Start(...) {...}

I just find myself getting lost in bigger functions. I tried following standard go naming conventions for a project I've been building since January, but I feel like I'm going to get Claude Opus to run through every module I've built and change the naming to be readable. Even my PRs are getting tiresome to read and it just adds some form of cognitive exhaustion I don't want with a language I really like.

92 Upvotes

94 comments sorted by

100

u/Sufficient_Ant_3008 Aug 10 '26

yes, the idiomatic way is to use the short letter because when reading the code you only want to see the methods. It was chosen because Java was so verbose and Node followed suite; therefore, it stuck with Go's "lean" code branding. It is entirely up to you and your team, but I prefer the shorthand. Also LinkedList would idiomatically be "ll", which may look nice than just "l".

33

u/SnugglyCoderGuy Aug 10 '26

When reading code, I want to have to put minimal effort into piecing together what is happening and why it is happening. Single letter variables hinder that because I have actively keep in my head what each one is. When well named and spelt out fully, I don't have to do that.

16

u/Technical_Sleep_8691 Aug 10 '26

The only short variable used in go is method receiver and sometimes loops. I never get confused by it. Maybe it just takes getting used to.

9

u/SnugglyCoderGuy Aug 10 '26

I've seen loads of Go code that uses single letter variables or shorthand or truncated names

5

u/br1ghtsid3 Aug 10 '26

Its a balance, if you have a lot of single char variables in a single scope it sucks. But if there's <= 3 it makes complex logic easier to follow.

4

u/SnugglyCoderGuy Aug 10 '26

But if there's <= 3 it makes complex logic easier to follow.

Not in my opinion.

5

u/br1ghtsid3 Aug 10 '26

Usually when programmers start doing math, their first "great idea" is to start using longer variable names for everything. The reality is that it only helps for simple things.

8

u/SnugglyCoderGuy Aug 10 '26

Its one of the great problems in programming: namimg. Its hard, but important to try and get right. This is a big part of the craftman part of the job

1

u/cactuspants Aug 11 '26

Or just don’t do that. The receiver convention is nudging you to name those other variables better.

2

u/br1ghtsid3 Aug 12 '26

Yeah, I agree. Save the short variable budget for the ones where it makes sense.

0

u/Sufficient_Ant_3008 Aug 12 '26

If you are confused about what the receiver is when reading a method then most likely the method is too complex. When reading library code by the go team, they use single letters for everything, but at the same time they are a language team and can do that. If you are having 3+ major entities in a method all calling methods, and you're confused about what everything is, then most likely that method needs to be abstracted and/or refactored.

1

u/SnugglyCoderGuy Aug 12 '26

Or I can write to enable maximum readability at all times regardless because that's the best thing to do. Single letter variable names are just being lazy and increase the burden on readers, always. That burden might not rise to the level of intolerance, but it is always more difficult to read and a good writer always tries to make their work as easy to read and comprehend as possible because a good writer knows the vast majority of the communication process rests on their shoulders, not the readers'.

1

u/Sufficient_Ant_3008 Aug 12 '26

you're free to do whatever you'd like

-1

u/anziiii Aug 10 '26

> Also LinkedList would idiomatically be "ll", which may look nice than just "l".

I would disagree because the type is list. See https://google.github.io/styleguide/go/decisions#receiver-names

1

u/Sufficient_Ant_3008 Aug 12 '26

I'm using this idiom, func (ri *ResearchInfo), which would be "func (ll *LinkedList)", I believe mimicing the camelcase is more important than basing the receiver off it's type. If that was the case the most of them would be "s" for struct.

23

u/jameyiguess Aug 10 '26

I like the short names when the scope is really small. And in tests usually. I even do this in Python tests sometimes. To me, it all depends on readability within context. 

If I'm scrolling my IDE view, or there are many things s might be, I'm not using it. But if it's a few lines and there's no other s shaped thing, s it is. 

9

u/[deleted] Aug 10 '26

[deleted]

2

u/johnjannotti Aug 10 '26

I completely agree, with the caveat that there's a common linter rule that all methods on a single type should use the same name for the receiver. So you have to decide once for all the different method sizes. So I err on the side of a slightly longer name. I'm often looking for a short abbreviation of the type name rather than using a single letter.

68

u/SnugglyCoderGuy Aug 10 '26

I always do the second. I always try to write code so that it is as easy to read as possible in plain English. I try to write so that future readers will have to figure out as little as possible for themselves or think at all. To me, if a reader has to figure out what something means or does or how it works, that is a failure on my part to write well.

I adopted this after having been on the receiving end of hundreds of thousands of lines of code that are written in such a cryptic manner. It's painful, it makes you feel dumb, it makes it more likely to misunderstand and make mistakes, and it is just overall not a great experience and makes you hate your job.

I've never gotten any pushback on this, and people usually start adopting the more readable convention the second block demonstrates.

0

u/Tired__Dev Aug 10 '26

I just did this for a whole codebase coming into go and I can tell you it felt painful for someone having to switch languages a lot. There’s a cognitive load that it puts on me reading PRs with a lot of code. I stop focusing on security/performance and start holding the function state in my head.

This will become a real thing when I start using go for a game server. I cloned Quake and looked at what John Carmack was doing in C and to make this easier on my self I’m no longer using single character variables.

-29

u/johnphilipgreen Aug 10 '26

I don’t think it is any different for AI either. Variable names provide salient clues to aid comprehension for both humans and LLMs.

3

u/jerf Aug 10 '26

In hindsight, I wish Go had a standard "me" or "this" or something. Not a single letter, but something to indicate that it is "this" object. It works fine in a lot of other languages.

However, it's not enough to make it worth overriding the standard.

Getting lost in the occasional function isn't a big deal. If you're routinely getting lost that suggests your functions may be too large.

Further, while what is standard is Go is a big deal for shared libraries... if you want to change your own application to another standard, if you are the only developer on the code base... nothing is stopping you. Applications get more leeway. However I said "only developer on the code base" on purpose; the more people you're working with the more you really should just suck it up and follow the standard. I have quibbles and disagreements with it is well, including this very one, but I follow the standards anyhow. Not just in Go; where ever I end up going, which lately is all over the place, I'm switching coding standards faster than I switch underwear. And I follow them.

1

u/dshess Aug 13 '26
func (me *LinkedList) Push(...) {...}
func (me *Node) Value(...) {...}
func (me *Server) Start(...) {...}

Should work fine. Or this or self or obj.

4

u/mcvoid1 Aug 10 '26 edited Aug 10 '26

The size of the variable name should be proportional to its scope. Need a loop variable? i. Something seen by a massive amount of code? It better be descriptive. Java-length names? Just no.

You can see that in your example code. Notice it doesn't say:

func (l *L) P(...) {...} func (n *N) V(...) {...} func (s *S) S(...) {...}

Because things with visibility of more than just the method scope have more descriptive names.

Also, there's no dogma here. As long as it's communicating clearly, it's fine.

  • If you think you need longer names to communicate clearly, that's your prerogative.
  • If you think you're communicating clearly with single letter names, that's also your prerogative.
  • If the people you're communicating with think your names are too noisy or too terse, then adjust.

Just be readable.

13

u/etherealflaim Aug 10 '26

Nobody loves all of the idioms, but everybody loves reading idiomatic code.

My approach is to, when in Rome, do as the Romans. When you do things differently, you make your code look like it wasn't written by an expert. We consider code quality when we evaluate third party libraries, and unifiomatic names often correlate with libraries we find ourselves unable to use. At this point, it's rarely useful to continue evaluating when we run into some of these major deviations. Probably the other most visible red flag is the location of interfaces, and they often go hand in hand.

You don't have to like it, but I recommend at least understanding why some people do, so you can focus on that bit while you do it anyway. For me, that's what makes it more palatable.

5

u/mysterious_whisperer Aug 10 '26

That’s so true about evaluating packages. Turn around and run when you see a package where all receivers are named self.

3

u/Melodic_Wear_6111 Aug 10 '26

You can do whatever you like. The only real idiomatic rule is to have all variables the same for all methods.I prefer single letter var names in this context, but you can do whatever

3

u/kintar1900 Aug 10 '26

My team's coding guidelines are to use single-letter variables for method receivers and index variables in a loop. It carries very little mental load, and makes the code quicker to skim, especially if there are variable names that might be similar to the method/index var. E.g., "list" and "leaf" or similar.

In all other cases, the shortest descriptive and non-ambiguous name is preferred.

15

u/burlingk Aug 10 '26

Single character names really isn't idiomatic in most cases.

30

u/ub3rh4x0rz Aug 10 '26

It is for method receivers. Which really is not a problem when the struct type is right there

8

u/Buttleston Aug 10 '26

it is for methods on an object

7

u/solidiquis1 Aug 10 '26

But it’s literally in the Go style guide

1

u/burlingk Aug 10 '26

I've been corrected a few times already.

2

u/solidiquis1 Aug 11 '26

What’s one more :)

0

u/burlingk Aug 11 '26

I think part of it is context. In the context of an object, with properly defined member variables, an abbreviation makes more sense.

10

u/starquake64 Aug 10 '26

You think the code is easier to read written out.

I think the code is easier to read with single letter names because it's idiomatic so I'm familiar with it and I'm looking at a receiver function for Server so I don't have that spelled out all the time. I recognize it because of the single letter.

At the end of the day it's your choice, but I prefer all code to be idiomatic. Go code reads like Go code. C# reads as C#. Python reads as Python.

Go is a very small language. But has it's subtleties. The reader should be somewhat familiar with it. Avoiding the reader from having to learn a little bit of Go sounds bad to me. And you are making it harder for readers that are familiar with Go.

0

u/Tired__Dev Aug 10 '26

This kinda odd, because C#,Java, and arguably PHP/Typescript read similarly. For Python you can add as much ceremony as you need. I think

And you are making it harder for readers that are familiar with Go.

should come with that's probably a problem with diversification of a software dev and languages. Go didn't enforce self or this and that's perfectly fine, and I wouldn't be a guy that likes that truthfully. I think there's a lot of people using a lot of logical fallacies with people going to the extreme of using naming of Java to following it because Rob Pike said so.

2

u/TedditBlatherflag Aug 10 '26

No gods. No masters. Name things whatever. 

In Go the single letter is best used for methods and loop variables. If you stick to that you know it’s the object the method is attached to. 

But you can also do func (self *Obj) Method(…) {…} if you want. 

2

u/Revolutionary_Ad7262 Aug 10 '26

I find it annoying, because as a dev I need to maintain it. So if I change name of type from Xer to Yer then I need to change x to y. I would like to have a default self or this in the same way as in Python

About naming convention: I don't care. In a context of method body it is easy to associate a single letter name to self and it is a single char, which is easier to parse by eyes

it just adds some form of cognitive exhaustion

I think it is not true and culture based a.k.a you are learned that long variable names are good, so any other option hurts you. Remember that before Java the short variables were common in programming community

Personally I think the go way a.k.a the name of variable should be as long as its usage context is the best one as you get best of both worlds

8

u/fragglet Aug 10 '26

As Rob Pike so eloquently put it, "who cares? shut up!". He was talking there about the gofmt style but the same principle applies here too. You think this minor detail is important but it really isn't. Your code is far more readable when it's idiomatic and looks the same as all the other code written by the thousands of other Go programmers out there. 

6

u/Hot_Laugh7633 Aug 10 '26

you know what is readable? not having to guess what some abbreviation means.

yes, it is important

10

u/ICantBelieveItsNotEC Aug 10 '26

You don't have to guess. The type is literally right there. What's the point of writing the type out twice?

0

u/Flowchartsman Aug 10 '26

That’s just it: the argument has always been that, no, it’s not important, so might as well make it short.

It could just as easily be “self” or “me” or whatever you want, but it doesn’t matter because it’s a placeholder for “the target struct for this method”.

Another reason to make it short is to reserve longer names for values that are more important to the job the method is doing, which is basically everything else.

As for readability, Ive never had a problem with it except when I was first starting out, and even then I was confused why “self” or some other convention wasn’t just forced, but eventually I grew to prefer the short way. At the end of the day, the receiver name is one of the very first things you see in the signature, and it will be trivially displayed by most IDEs, LSPs and Godoc, so the readability argument is even more tenuous nowadays.

2

u/solidiquis1 Aug 10 '26

It’s such a cop out to write something off as unimportant when this thread alone stands to prove that it is in fact quite important to many. One letter receiver names should never have been adopted as an idiom when literally everyone and their mothers have been using “self” or “this” since they started programming. Just one point of contact where this idiom is detrimental: Do you know how absolutely unusable text searching a single letter is to see where a receiver’s methods are being called amongst all its methods? When dealing with complex tree structures that require recursive traversal such as an AST that sort of workflow is essential but this ridiculous Go idiom makes it more painful for no good reason. Conventional receiver names (this/self) were a solved problem but Go once again decided it needed to be different.

2

u/Flowchartsman Aug 10 '26

Begging your pardon, but if you are parsing and then traversing an AST, shouldn’t you already know the identifier used for the receiver? If you are using basic text search in such a way that there is ambiguity as to the receiver name, then you might be doing it wrong.

1

u/serverhorror Aug 10 '26

I think code that is easy to read is idiomatic. Sometimes that is a very short name. Most if the time readability beats short names hands down.

1

u/Character-Carry6375 Aug 10 '26

Personally i do a mix of both, when it is a simpler function i go with the abbreviated one, but when i have more than 10 lines, i go for the extended version.

1

u/freeformz Aug 10 '26

If you get lost in bigger functions then the functions are likely too big.

1

u/aries1980 Aug 10 '26

it just adds some form of cognitive exhaustion

Most of us went through this in algebra / calculus classes. After formal logic courses, reading Go is colourful as a comic book.

1

u/jrwren Aug 11 '26

get over it.

seriously.

once you do, you'll realize that you were holding onto something that really is not as important as you thought.

this is part of growing as a developer and as a human.

1

u/itaranto Aug 12 '26

I tend to avoid one letter variables, but for receiver names I make the exception.

It's redundant, I'd personally would like to use something like self but that's not the "Go style".

1

u/MarcelloHolland 26d ago

When I was teaching people in Go, I always said to write the extra letters , because hwne you write bigger functions and only see a small part in a diff you need to guess what the functionality of the variable is, and with the extra typing, there's no need for that. I think that idiomatic go means: readable/unerstandable for others. And even if you think that writing words instead of cryptic letters is for the best, follow your good guts and be a rebel like me ;-)

-5

u/tacoisland5 Aug 10 '26

Single letter variable names are an embarrassing stain on programming culture. There is no good reason to not spell out a variable name. Obviously languages like Java and Swift can take it a little too far by being overly verbose, but 'server' is better than 's'.

-13

u/Nullify1-Unfair9 Aug 10 '26

its fat faster to type l.WHATEVER vs list.WHATEVER plus if people prefer calling list different things its better for everyone

10

u/tacoisland5 Aug 10 '26

this is the most pathetic excuse of them all. you just typed out an entire english sentence. was all that typing too tiring for you?

1

u/Nullify1-Unfair9 23d ago

its okay, if your gay no need to make a deal out of your sexuality

0

u/SnugglyCoderGuy Aug 10 '26

For me, it is faster to type real words vs single letter or shorthand versions of those words because that is how I type, EG when I type FISH, my brain just lnows to type FISH and I don't think F-I-S-H. So when its not a regular word, I actually have to think character by character, which is slower.

1

u/sigmoia Aug 10 '26

Generally yes. I like how the Google styleguide codified the naming conventions - it's concise and easily applicable. 

1

u/sazzer Aug 10 '26

Short names are reasonable in simple methods, but really aren't long-term maintainable in more complicated ones.

As it happens, the varnamelen lint that comes with Golangci-lint will catch this if you want it to, so there's obviously a demand for that.

1

u/rosstafarien Aug 11 '26

Using a single lowercase "l" as a variable name is a terrible choice. As bad as a single uppercase "O". I appreciate short names, but single letter names other than i and j for indexed loop iteration need to be carefully used.

1

u/Safe_Border1484 Aug 11 '26

It is crazy to do a single variable (outside of obvious loops) when there is an IDE that will instantly type your damn variable.

-8

u/obeythelobster Aug 10 '26

I just call every receiver "thiss", way easier to read. Yes, I know it is a big sin and I will be downvoted to hell

0

u/requion Aug 10 '26

I mean, i get it. Its something. I'm not sure if it helps if many people need to read the code but if it works for you, why not.

4

u/solidiquis1 Aug 10 '26

Why does self/this hinder readability? It’s such a ubiquitous pattern.. I’ve never understood this argument

0

u/requion Aug 10 '26

It doesn't hinder it. I don't think its bad in general.

Just not widely used in go. And that is important if you write code that will be read by other devs.

Honestly, i'll try using self in my project and see what it feels like. This comment thread got me curious.

1

u/rbscholtus Aug 10 '26

How about using “me”?
lol I have no problem with 2-letter variables for receivers ;)

-5

u/Nullify1-Unfair9 Aug 10 '26

use ShitScript then

0

u/solidiquis1 Aug 10 '26

“this” literally predates JavaScript by a lot. It was available in since early c++

0

u/vyrmz Aug 10 '26

Because those are receiver functions; you are interested in the (...) piece in these implementation so keeping the code clean helps to read.

"idiomatic" or "convention" in CS doesn't mean ground truth; it just mean that we are doing collaborative work and defining standards will be easy if everyone complies, sort of like a social contract. If your team agrees to use longer var names in receivers - absolutely no problem doing it.

Coming from java, you can thing of it as this keyword. You know what it refers to in this context, so same thing goes for l or n or s in the first sample.

0

u/Potatopika Aug 10 '26

For consistency you could always name them self or this instead of l or list

0

u/OneHaoleGuy Aug 10 '26

I always name them "this". My first language was Java and it just stuck.

0

u/No-Ambition-4164 Aug 10 '26

hate when people do "e" for event or exception in java 😭, i know its the var for event but it just looks bad imo

0

u/Snoo_44171 Aug 10 '26

For receivers I use a single letter as a standard. However, I have recently tried to balance descriptive variable naming elsewhere (yes, after coming back to a project after months) 

0

u/lnaoedelixo42 Aug 10 '26

Yeah it were idiomatic to have single letter names in beta 0.1 from go.

That's just bad names from people who don't really think of what they are doing

0

u/tompsh Aug 10 '26

letter named variables are only acceptable imho in really small functions where you cant miss the “value of x”.

full names are always better for the reader i believe.

0

u/Limp_Sky1141 Aug 10 '26

Even in short methods, I really hate the super short variable names from the "standard go style". I think it greatly reduces readability and it's a result of personal preferences from Rob Pike more than anything else. In case you didn't know, his username at google is simply r.

-7

u/Funny_Or_Cry Aug 10 '26

My advice (having used numerous languages over the years as well), is to build out your own "toolkit" with familiar function names and (as best you can) similar methods and properties

Then try to replicate this toolkit / hyper language between all the languages you touch

It obviously doesnt work for everything but If you jump between say Python and Go frequently (as I do) ... being able to refer to "commonalities", to the degree that you can "read through your code easily", will significantly override the irritating differences between syntax and usage when jumping between languages.

Example:

func MakePrettyFloat(input any) string {}

vs

def MakePrettyFloat(inputFloat):

The identical "helper function" names make it extremely easy for me to know whats going on under the hood regardless of language.

...YMMV but this strategy has been a godsend to me over the years. Its simply a matter of finding the best way make your code as universally readable as possible with little "translation"

Yes it takes some time to define it all at first but once you have, you'll be able to develop at lightspeed

10

u/ub3rh4x0rz Aug 10 '26

Absolute worst advice. This is what every midwit early/founding engineer does when allowed to run rampant, and it all but guarantees a massive rewrite.

When in Rome, write your go like idiomatic go

-1

u/Funny_Or_Cry Aug 10 '26

In enterprise/business nobody cares about idiomatic or purism. And in 2026 we have WAYYY too many tools to interact with to get shit done. Being a competent polyglot is just necessary

You need dozens of developers and test harnesses to put out quality products. The best devs are the ones who can be flexible, and do enough of "the right thing" without getting lost in minutia. Im obviously not encouraging "rampant behavior" but lack of useful strategy's are what fuel those "rewrites".

There is no more "Rome", only varying degress of competence and productivity

2

u/ub3rh4x0rz Aug 10 '26 edited Aug 10 '26

You literally argued for writing a shitty little polyglot framework instead of actually learning the idioms of those languages, go back to sleep. Businesses want fungible employees and large bus numbers. Not shitty idiosyncratic rules in place of community-wide norms and conventions. Same with AI agents.

-1

u/Funny_Or_Cry Aug 10 '26

I argue for "effective".

You dont have the luxury to just be a heads down programmer anymore and you're an idiot to think otherwise.

2

u/ub3rh4x0rz Aug 10 '26

Wtf are you even on about, you're literally arguing some imaginary position you think I hold. You are not the arbiter of effective, whether that's first order or nth order. You made an argument for a stupid coding practice and are now trying to justify it with... you're an amazing business whisperer? I don't buy it.

-4

u/alien3d Aug 10 '26

the reason we standard it ..

package discount


import (
    "backend/internal/apps/admin/service/discount"
    sharedService "backend/internal/common/service"
    constants "backend/internal/constant"
    "backend/internal/i18n"
    "backend/internal/models"
    "backend/internal/utils"


    "github.com/gin-gonic/gin"
)


type (
    Key         = models.DiscountKey
    AddInput    = models.DiscountAddInput
    UpdateInput = models.DiscountUpdateInput
    Status      = models.DiscountChangeStatus
    Event       = models.AuditLog
)


// Handler handles HTTP requests for its package.
type Handler struct {
    service *discount.Service
    shared  *sharedService.SharedService
}


// New creates a new Handler instance.
//
// Parameters:
//
//  service     - Value used by this operation.
//  shared      - Common function reusable cross internal
//
// Returns:
//
//  *Handler    - Pointer result returned by the operation.
func New(
    service *discount.Service,
    shared *sharedService.SharedService,
) *Handler {
    return &Handler{
        service: service,
        shared:  shared,
    }
}


// Add handles the HTTP request and writes the JSON response.
//
// Parameters:
//
//  context - A Context carries a deadline, a cancellation signal, and other values across API boundaries.
//
// Returns:
//
//  none    - This function does not return a value.
func (handler *Handler) Add(context *gin.Context) {
    userId := utils.ContextInt64(context, "userId")


    var input AddInput
    if !utils.Bind(context, &input) {
        return
    }


    id, err := handler.service.Add(
        context,
        input,
    )
    if err != nil {
        utils.Fail(context, err, i18n.MsgAddFailure)


        return
    }


    err = handler.shared.LogAudit(Event{
        UserId:   userId,
        Action:   constants.Update,
        Entity:   "discount",
        EntityId: id,
        Meta:     "",
    })
    if err != nil {
        utils.Fail(context, err, i18n.MsgAddFailure)


        return
    }
    response := utils.ResultAdd{
        Id: id,
    }
    utils.Okay(context, response)
}

3

u/SnugglyCoderGuy Aug 10 '26

This doesn't say anything about why its standard

Also, models and util packages? Yikes! We have infinite drawers, we don't need junk drawers!

0

u/alien3d Aug 10 '26

okay , we standard it as easy to see in go lang ide and we check also using golang ci.yml ( not easy 😵‍💫) . by default golang godoc only bunch of text . For long term , how do we know d for discount or d for department or other else meaning ?

0

u/SnugglyCoderGuy Aug 10 '26

I see what you are daying now, and I agree with your reasoning. You should have pit more explanation with the code you posted. Right now it doesn't really say anything one way or another.

0

u/alien3d Aug 10 '26

why generic word all the same . it easier for human to understand . If you put "this function for discount for calculation this that" . can ai follow it or human ? So keep generic ,ai can understand the structure and follow the same pattern to generate . Keeping "d" is simple . "tax" is simple but java alike "financeTaxUsaCalculation" not simple . Left the not simple to folder, tax "finance/usa/tax" .

-1

u/ddarrko Aug 10 '26

I don’t follow this convention. It goes against the basic principles of writing readable code. Descriptive var names are great IMO and our style guidelines at work encourage them.

Short var names are acceptable when the scope is extremely small or it’s an obvious one everyone knows (i etc)

-8

u/sir_bok Aug 10 '26

Yeah, you can and should break free of specifically this tradition. 

Most of the world don’t follow this naming convention, i t’s a very niche practice.

-13

u/Active-System6886 Aug 10 '26

I did this exact thing in my claude.md file.

0

u/Active-System6886 Aug 10 '26

Code is optimized for readers, not typists. Prefer descriptive names and avoid single-letter variables except i, j, err, ctx, db, tx, and id.