I have a project that I worked on back in 2013 that I’m thinking of revamping. It’s a pretty straightforward CRUD web app for tracking stats for an older video game. The basic capabilities are parsing a text file (save state), interacting with a database, and returning json data. The rewrite will be the same thing for the most part, but there are a few things I wanted to fix and I have no interest maintaining the old code.
Right now, my initial thought is to use Python because.. well I like python! But I also realize this is a good time to try something new since it’s a personal/passion project.
So let me have it, why should I use your favorite language/framework/library?
I always suggest Go. If this is a project that will be “complete” soon, then you have good chances to release your code after years, compiled with newer versions of Go, without the need to rewrite it. (If you used standard library packages.)
Unfortunately, writing CRUD in Go can be tedious because there are no generics, but this is fine. Later, when you realize that your abstractions where wrong, you will thank Go for the lack of generics anyway.
I’m sure this is more true today, but when I wrote a few Go projects several years ago, it sucked trying to compile them again on a new machine because the dependencies were all screwed up. I can’t believe Go went so long without good dependency management. Well, I guess I shouldn’t be surprised because there’s Python…
In any case, Go-the-language was pleasant to work with. I hope the recent work on dependency management has made it much smoother to actually compile an older project.
Funny, I haven’t felt the pain of no generics when writing Go CRUD apps, but rather I’ve felt the pain of writing out a bunch of SQL queries and getting a nice “get all” endpoint for each object with filtering. I know ORMs are a thing, but I feel like they’re (almost) an anti-pattern in Go - at the very least I never see them recommended.
sqlc is pretty great https://github.com/kyleconroy/sqlc
JVM backwards compatibility is great too.
I don’t want to sell you on my favorite language, but on my favorite method.
Do you want this thing to just work? Choose a boring tool.
Do you want to spend the least amount of time? Choose something you’re familiar with (unless it’s ill-suiter for the task).
Want to learn a new language/framework and have more time to complete it? Choose something you want to learn that doesn’t seem to be outdated in a year, or you’ll keep rewriting it again in 2 years.
What I would choose right now? I’m learning Erlang atm, so I’d try to get this done with Cowboy. If not, Python is a solid choice, but so are PHP or Go.
I’m a fan of Rust, and I think it’s a reasonable choice for a personal project language. It’s more or less as suited for writing a CRUD webapp as any of the dozen or so popular general-purpose programming languages in widespread use. It’s an increasingly popular industry language, so knowing how to write code in it has a good chance of improving your marketability as a professional programmer. The language semantics and tooling do a lot of innovative things that many other mainstream programming languages don’t in my opinion (ML style types, memory safety in a GC-less context,
cargo
and related build tooling).I might also suggest writing it in Haskell, if you’ve never touched Haskell or a similar functional programming language before. It’s a genuinely different way of thinking about programming from more mainstream languages.
I had thought about suggesting Haskell, it’s the language I would absolutely choose to solve this problem in (whip up some Servant web API types, chuck in some postgresql-simple/beam/selda/whatever the new hotness for DB access is, parsing is trivial in Haskell, etc.) but there’s a lot to learn before you can get something useful done in your first project - it’s pretty simple to cargo cult a python web app, it’s not so easy to do in Haskell because the language is much more strict about what is acceptable (at the benefit of allowing you to be much more expressive about what you think should be acceptable, and having the compiler tell you when you got it wrong).
By all means, OP should learn Haskell, but it’s to really the right choice for a one off project like described - but then again. no language worth actually learning is either, I’d say the same about Rust, C++, Julia (probably) too.
Give Ada a shot. It’s used in high-reliability contexts, is ISO-standardized, has been in development since the 70’s and constantly updated and has had a pointer ownership model long before Rust came and claimed to have invented it. Admittedly, it’s not as “cool” and your code looks “boring”, but is very well-readable. The type system is also very strong (you could, for instance, define a type that can only hold primes or a tuple type that can only contain non-equal tuples) and even though Ada is OOP, which I generally dislike, they’re doing it right.
Additional bonuses are a really strong static analyzer (GNAT prove, which allows you to statically (!) verify there are no data-races or exceptions in a given code based on the Ada Spark subset) and parallelism and concurrency built into the language (not some crate that changes every week).
Many claim that Ada was dead, but it’s actually alive and kicking. Many people are using it but are just not that vocal about it and just get work done. As we can already see in this thread alone, the Rust-evangelists love to spread their message, but if you ask me, Rust is doomed due to it’s non-standardization.
You wouldn’t build your house on quicksand (Rust), but bedrock (Ada).
How is the web stack stuff in Ada? Database access? It seems very interesting, but the ecosystem might not be in place for this specific application at least.
Learning Ada at university for concurrent and parallel systems course, and real-time and embedded, showed me that C being the default for those domains really was a mistake. Ada has a very expressive concurrency model, I haven’t seen anything like it anywhere else (I love Haskell’s concurrency features equally, but they are very different). The precision you can express with Ada is amazing; the example in our real-time course was defining a type which represented memory mapped registers, could precisely describer what every bit would mean, in one of (IIRC) 8 alternative layouts depending on what instruction was being represented, and the type could be defined to only exist at the 8 memory locations where these registers were mapped. To do the same in C requires doing things which can only be described as hacks, and don’t tell the system important things like never allocate these addresses, they’re used for something already. The world has lost a lot by not paying more attention to Ada and hating on it without knowing the first thing about it.
Ada looks really interesting to me because of all the checks you do at compile time, ensuring your program is correct before even running it. It’s also much more readable than something like, say, Rust. I would love something in the middle of C and Ada, with lots of compile time checks and the flexibility of C.
After two days of kicking the tires on Ada, I’ve had nearly every opinion I had about it broken in a good way. I’m baffled I’m already productive in a language that feels like I’m being paid to write extra words like a serial fiction writer, but every so often, there’s some super useful bug-preventing thing I can do in a few lines of Ada which would be prohibitive or impossible to do in other languages (e.g. dynamic predicates, modular types).
The compile time checks it uses by default are in the vein of “if it compiles, it probably works” like Haskell or Rust. Within the same program you can turn on more intricate compile time/flow checks by annotating parts of your program to use SPARK, which is a subset of Ada and can coexist in the same project with your other code. The best way to describe it is almost like being able to use
extern C
within C++ codebases, orunsafe
blocks in Rust to change what language features the compiler allows. Except code seems safe by default, and SPARK is “This part is mission critical, and is written in a reduced subset of the language to assist verification: e.g. functions must be stateless, checking of dependency of function inputs/outputs, etc.Let’s say I’m sold on this: what’s the best way to learn ada for - say - writing a web app or doing etl?
I would do much like I do for any other language, throw some terms into Google and go from there. I’d download GNAT, play with some toy programs and maybe try out Ada Web Application.
Right, I threw in some search terms but I was wondering if you had any insights beyond that. In particular, how do people discover ada packages?
I’m sorry, I didn’t know if you being sarcastic. Sigh, the state of the internet these days.
Honestly, I have no idea. I’m just googling around trying to figure stuff out and this language feels like crawling into the operator seat of an abandoned earthmover and wondering, “What does this level do?” I used to work on ships with life-or-death systems and Ada feels much along these lines and industrial (as from an industrial manufacturing or maritime environment, not a bureaucratic, office, or software based one). They don’t use a tool because it’s popular, they use it because it does the right thing within the technical specs, and can be easily documented and prevents mistakes because people’s lives depend on it.
To answer my own question, it looks like there is a beta package manager and index that provides a jumping off point to find stuff https://alire.ada.dev/search/?q=Web
Neat! I hadn’t found that yet.
I poked around a bit last night and found that the Adacore Github account has a lot of things like unit testing (AUnit), an Ada language server, and a lot more than I thought would be there. My first major gripe is that gnattest isn’t part of GNAT community, and the AUnit links were broken, but I finally found it on that account. I still need to crawl through how the build system works and such if you’re not going through a package manager.
If you have access to an Oracle installation, dive into your orgs stored procs. PL/SQL is Ada with a SELECT statement.
Thanks for your detailed elaboration which I can only agree with!
And on top of all those guarantees and safeguards, you can easily write parallel code (using tasks) that is ingrained into the language. I find this truly remarkable given it actually makes sense to write web applications in Ada because of that.
Have you tried D? It works as a flexible language where it looks like Python. Yet you can tighten it up with annotations (const, safe, …) and the meta programming can do plenty of compile time checks like bounded numbers.
I have thought about D, but it seems to fall right in the middle of lower and higher level languages. It lacks a niche, as I see it.
I might be wrong though, I have yet to try it after all.
Update: I checked it out, and it actually seems really interesting. I’ll try it out tomorrow.
I had the same thought as you when I first looked into Ada, thinking that it may provide safety but at the cost of missing closeness to the machine. However, you can get really close to the machine (for example bit-perfect “structs” and types). On the other hand, yes, if you add to much of the flexibility C provides, you end up with possible pitfalls.
That’s Pascal.
You could do a lot worse than trying Lua via OpenResty. It uses the lua-nginx-module to bridge nginx and the LuaJIT, giving you a slick package incorporating a powerful, fast web server and language runtime environment with tons of package-managed quality libraries, including some solid web frameworks. It’s basically nginx’s guts exposed neatly in a well-organised async Lua API, so you’re effectively scripting the entire non-blocking web mechanism using a clean, simple language that lets you layer pretty much anything you want on top, from a straightforward web app to per-request load-balancing decisions and scriptable TCP socket servers. Pretty amazing.
reserved +1 for Lua and openresty. Last I checked it was a bit of a pain to install/deploy if you just diverged a little from openresty’s default packaging method after they somehow made it hard to just compile it. (or to install libs with luarocks, I don’t remember the details)
I used it with Lapis and it was pretty enjoyable.
Yeah it definitely used to be quite fiddly to install and custom build in particular. That’s something they’ve been working on a lot - there are deb/rpm/etc packages for the standard distribution, and the bundled
opm
package manager makes installing OR packages really easy now, althoughluarocks
works fine too. The tooling in general has improved with the CLIresty
tool making things easier to quickly try things out in isolation. I have a custom build script with a couple of other nginx modules that I’ve been using for a while which works fine so I haven’t been directly exposed to the build process for some time, but traditionally it was quite a pain. Fortunately the packages now come with “batteries included” - and I’ve just finished a project where I used it both in Docker and Packer images, and it was as simple as installing the PPA and runningapt-get install openresty
:-)That sounds great, maybe I looked exacctly in the transition phase where opm was lacking (packages mostly) and luarocks was kinda broken (or suggested to not be used) so even shoehorning lapis into there was a pain.
If you want to something really new, I will try Janet programming language https://janet-lang.org/.
The language and ecosystem are very young, but you mentioned parsing text for which Janet has powerful tools in the language’s core: the PEG.
Feel free to contact me if you need further advice. I am a co-maintainer of the packages registry for the language to help you choose the right tools.
Haskell.
There are some things it’s extremely good at, but I think it’s worth learning because it’s a very different way of thinking about code than you’re likely used to. The lessons learned will travel with you to other languages.
Most notably, after learning Haskell, I find it maddening that other languages don’t have any notion of enforcing purity outside perhaps variable mutation. It encourages code that’s readable, testable, and composable, and speaking of readability it allows you to take mental shortcuts that mightn’t be obvious if you’ve never worked with this style of code.
Likewise function composition allows you to take some mental shortcuts; when practicing type-driven development, I can picture the data transforming from
a
tob
on either side of the composed function without thinking about what’s going on in there internally. This, alongside the tendency to encode the unhappy path in the type system, is I think what gives many Haskellers that feeling of “if it compiles, it’ll probably work”.You should give a serious thought to Common Lisp. It’s still an unmatched platform. It offers:
Here’s my comparision of the workflow and ecosystem with Python: https://lisp-journey.gitlab.io/pythonvslisp/
and a State of CL 2020: https://lisp-journey.gitlab.io/blog/state-of-the-common-lisp-ecosystem-2020/ (with nice comments on HN, see link in comments)
I hope the Cookbook is useful: https://lispcookbook.github.io/cl-cookbook/ It greatly improved in the last years, hopefully answering many newcomers’ concerns.
PS: CL is not tied to Emacs any more. Find good plugins for Atom (SLIMA), VSCode, vim, Sublime…
I’m a big fan of CL myself and this cl-cookbook looks awesome. By far my biggest complaint compared to, for example, Elixir is the quality and accessibility of library documentation. I’ve done some cool little projects in CL, and a significant amount of time in all of them was spent just figuring out how to use the libraries appropriately.
If your language doesn’t have a rationale page, then they should get around to adding it so you don’t have to rely on people posting comments about it on some random site! Here’s the one I wrote for Fennel: https://fennel-lang.org
Apparently I took to long to notice I screwed up the link so I can’t edit; the actual link is https://fennel-lang.org/rationale
for CRUD, I highly recommend Elixir.
Here’s a pitch I wrote for Clojure. One major advantage with Clojure in web dev space is that it runs both on the server and the client. Here’s comparison of different front-end frameworks for a real-world app, and Clojure does consistently well in terms of bundle size, speed, and conciseness.
Clojure is a delight to use, and immensely practical as a language to work with as well. Clojure is stable, has stable library support, can access the full enterprise legacy of the JVM, and can be made to run damn nearly everywhere without too much effort.
It’s hard to oversell this last point.
It’s not only possible (but surprisingly easy, and I’ve done it!) to write a single application that can run:
It can accomplish this feat since it can target JavaScript Runtimes and the JVM, which was yesterdays “Big fat VM binary”, but has a really tiny footprint compared to other technologies with such broad deploy bases.
I think if you try it, you’ll find that you’ll begin to reach for it for everything and be better off for it. The only major criticism that I’ve seen leveled against the language is that libraries are rarely updated, but I can speak from experience it’s because they’re really damn good and there is little or nothing to change or improve.
Also in terms of fun languages and building up your CV, Clojure is a Lisp dialect, and Lisp is a superpower.
You should learn a new language only if it learns you something along the way. Some language can be put in a “bag” of similar patterns:
I’m not sure this is fair, I’ve been developing using Haskell for about 6 years now and we’ve completed plenty of projects. In fact, one of Haskell best features is the ability to fearlessly refactor; when new requirements come up, we just make the obvious change and the compiler guides up to all the places we forgot about. This makes experimentation also very cheap, but only once you’ve learned the language enough to be proficient and know the patterns to use and avoid to help the compiler help you (big one for me is always using total case statements, unless it’s a situation where you know there’s a single thing you want to match and everything else is invalid).
Learning Haskell to the level of pragmatic productivity for an average software developer sometimes literally takes years.
Not a single experienced Haskellite would argue with that sentence. Anyone who would - probably hasn’t ventured deeply enough into quite complicated ecosystem of Haskell.
Hm, so, as someone who literally did language evangelism for quite a while now (Ruby and Rust for over a decade): I’d stick with python and maybe use something current like modern Django or one of the smaller frameworks. If you really want some fresh air, maybe switch to a language close to it, like Ruby or even PHP (with all its bad rep, there’s a reason PHP is still the dominant language).
Given that you don’t want to maintain the old code, trying out a new ecosystem on your know problem will almost surely yield the next code base that you don’t want to continue to maintain - especially if the ecosystem is far out.
Also, given that it sounds like the app has a web part, I’d avoid all things Rust. Not because I don’t like it, but there’s not stable web frameworks and their general security/templating stack is very diverging/incomplete (e.g. things like safe cookie handling, CSRF, XSS, and such). So you either forgo the whole problem or you have a lot of things to investigate. APIs, I’m less hesitant, but for the rest, the story is still very spotty.
That all being said, taking slices from your problem and reimplementing it in languages you want to try is a very useful method of learning, but I’d prepare myself for throwing the code away. Detaching learning from necessary success also makes the thing far more relaxing.
Completely agree, sadly. Recently I poked around the Rust web landscape looking for a web framework with one simple criterion: uses up to date dependencies. I couldn’t find anything that actually uses the latest version of hyper besides warp, which isn’t a framework so much as an HTTP server toolkit.
And the most downloaded framework on crates.io, Iron, is essentially unmaintained at this point.
The Rust web ecosystem is growing fast, with tons of promising work. But it’s not mature by any stretch of the imagination.
Give asp.net core a try with C#. Good en framework, good ORM, good db support and all the goodies. Works well with VS code.
If you prefer FP, go with F# instead. You still get to reap the benefits of .NET ecosystem. For web apps, I recommend one of the following:
doesn’t it require an ide? edit: i guess it doesn’t really matter if everything works in the end. excuse me for being negative.
Not these days! https://docs.microsoft.com/en-us/aspnet/core/getting-started/?view=aspnetcore-5.0
IDE is strictly not required but dotnet5.0 apps work great with VSCode on all three platforms.
Give Janet a try. It has an amazing built-in PEG module, which is a breeze to use. There are SQLite bindings and an SQL library that supports SQLite and Postgres. There’s also a web framework and a more Sinatra-inspired web framework.
Apart from library support, the documentation is very good, the Core API is full of useful functions for list comprehension and the like, and it has a very comfortable REPL. I’d say you’d finish at least a prototype of it very quickly in Janet.
AS of 2021 if you are interested in a production ready, widely used and supported language that can run on-prem and in the cloud with ease I would recommend F#.
It is almost comical how easy is to get productive in F# even is you have no idea about functional programming just want to write for loops and return nulls. Once you understand that map / reduce style functions are nicer and Option is a better (safer anyways) way of dealing with missing values you are going to have a better time. If you also start to grasp that AND / OR relationships are easily expressed with a type system that F# (and Haskell and other ML languages) have you realize that you can implement poker purely in types and with very few functions in a self explanatory way. (https://fsharpforfunandprofit.com/series/designing-with-types/).
Later on you can wonder into railway oriented programming and get rid of visible branches in your code.
All of these are optional, you can use F# on the level that you are most comfortable with. This is why F# is a beginner friendly language as opposed to Rust.
I recently chose F# for new apps, although I’ve been using Haskell (and still do!) for the past few years.
F# is not “purely” functional like Haskell is, but the trade-offs are worth it because you get access to a solid cross-platform framework and ecosystem. The full-stack development story (SignalR, Blazor) is also getting better, and moving faster, than in Haskell - thanks to investment from Microsoft and the community.
How is the performance of Blazor? It seems like it might be a bit heavy weight.
You can check for yourself: https://srid.github.io/fsharp-wasm-static-demo/
Click the title to see the source.
Once it’s loaded it’s pretty speedy, but the load is a bit slow. Is that load time the baseline that one could expect?
The initial load is due to the downloading of .DLLs to run on .NET runtime wasm in the browser (check Chrome Devtools Network tab). Microsoft is working on optimizing this part of the app.
If you want something that is lightweight, and directly transpiles to JS, I’d checkout https://fable.io/ - but this is different from running .NET on the browser (for Haskell people, this is like difference between PureScript and GHCJS).
Purescript is a great sort of mind-altering experience, if you have the patience for it during the learning phases.
You get the base goodies of an ML-based language, but you get a couple extremely important details that completely change the name of the game:
strict evaluation by default. I don’t actually like this but it does mean you don’t have to read a bunch of “Haskell lazy evaluation” discussions all over the place. It does what is written.
Built-in dictionaries (as records). You don’t have to go building a bunch of data types by hands, you can just write out a JSON-looking structure and use that to hold your data. Type infrerence “just works”.
Row effects! You can just say “take these two objects and merge them” and you just get what you want. You can have your lightweight object declarations and your type checks.
No more “OK this is pure or this can do any IO whatsover” type signatures. You can label your methods for extremely specific variants of IO. My favorite version of this is labelling a function as being “read-only”: you can read data from the DB, but no writing! Extremely valuable in my opinion and I think we’ve only scratched the surface here.
Relatively painless FFI, so you can always just cheat if you need to.
How is the documentation for Purescript?
I think Purescript By Example is good, though to be fair I had gotten into Purescript after looking at a bunch of Haskell stuff so I was already “in the space” so to speak.
I think Purescript Cookbook is also a good strategy for finding out how people might do X/Y/Z.
I really can’t stress how much the FFI helps my stuff cuz I can just bail on the functional stuff if I “know what I’m doing” though.
If your project is mostly CRUD, you don’t need a server side component other than your database.
Just put postgrest in front of your database and proceed to impleme te the UI with whatever you would need to use anyway. https://postgrest.org/en/v7.0.0/
You might need to write some PL/pgSQL, but this will be an order of magnitude or two less code than you would need otherwise. The reason being that you can work directly with references to the database. Instead of a whole lot of silly piping.
I think you should try Rust. No good reason aside from having your own point of view on a programming language that supposedly solves the pointer/memory error issue of programming without GC.
I would advise that you stick with Python and modernize your code and practices. For example, you can use static types to your python code or if there’s a part of the code base that is number-crunching, you can try to implement it in Rust or something else and use FFI, …
Python is a really decent choice and don’t chase the new shiny things just because you can! Many people are still using Python and get things done!
I still use C. Don’t use C; at least not for web development. I like Node.js for web stuff.
Express.js is my tool for everything Nginx can’t do on its own (except gitweb, which is a Perl CGI script). Most of my pages are static, but templating with EJS is easier than slapping PHP onto HTML. Wrapping one’s head around the different ways to do things can be frustrating, especially with many libraries providing promises, asynchronous callbacks, or standard synchronous APIs. I still don’t know how to use promises, and haven’t found a good reason to with how tiny my apps are. It’s also really nice to have everything including your config, messages, server code, and client code in the same langauge.
If you want to use C, Kore.io’s documentation is underwhelming at best and misleading at worst. BHCS seems cool, and parsing JSON with jsmn is very easy. Alas, footguns aplenty and I just crawled back to Node for anything web-facing.
For a database, I either roll my own simple thing using the filesystem, or pick between PostgreSQL and SQLite. SQLite is easier to set-up and is infinitely more portable. You can just up with your files and walk with the database in your pocket instead of having to fiddle with system services and actually configuring your database, which means less shit to fuss with on my desktop. With the hobbyist volume I work with, SQLite is more than enough.
Python seems like a fair candidate, but I’ve never used Flask or Django or anything, just gave WSGI half a shot back several years ago. Same with Perl. PHP is really the only other web langauge I’ve used as extensively as Node. I’ve heard it’s gotten better. If you really want to shoot yourself in the foot, give it a shot in Bash!
You use C and Node? Can you confirm my long-time suspicion? Does Node - at least in parts - remind you of C, and how? I don’t write C, but I learned some back in the 90s and I always thought working with Node reminded me of that C period.
Working with C and Node are two totally different paradigms to me. Working with Node or JavaScript (at least ES6) doesn’t remind me of C at all (besides the keywords and syntax, such as looping, branching, and functions (except
let func = (x) => { do_x_stuff...; }
and callbacks, which can be done with C using function pointers)).More often than not, I hear people refer to JavaScript as “Lisp in C’s clothes,” which may be a more accurate description: it reads like C, and is a fine functional language. Writing C in a functional fashion is possible and my favorite way to write C (you might give John Carmack’s advice on using C++ functionally a read), but it doesn’t remind me of Node at all.
The environment around Node is radically different from the environment around C. There’s no good C package manager (unless you argue for a VCS or a system’s package manager), objects do not have methods (a function pointer, sure), allocating one’s own memory is an issue, anonymous functions are non-existent (but clever use of macros is real), error-reporting is based on return values and not exceptions (not without a longjmp or something), and the toolchain is completely different. For example, to add another source file to a program, it must be in the Makefile (or whatever build system) and the build updated, and executed if no compiler errors. In Node, a simple
#!/usr/bin/env node
on the first line and your program is running without intermediate steps.In what ways does working with Node remind you of C? I can see Node’s pass-by-value and pass-by-value-of-reference stuff reminding me of working with C’s variables and pointers to some point. Ultimately, working with them is two totally different processes for me. YMMV with an IDE!
I probably don’t have all the information I need to make a recommendation for you specifically. I can only tell you what options I’d be looking at. I’m going to surprise myself a little by suggesting TypeScript. Like a lot of JS devs, I’ve already started writing TypeScript for my day job. There are at least three other languages I’d reach for first that I consider more fun to write. But two of them have already been mentioned (Haskell and Elixir) and the third (Elm) doesn’t have a back-end runtime (unless you count Lamdera, which is still in alpha), so it doesn’t sound like a great fit for your project, especially you end up writing all the guts in Python and your use of Elm is limited to an upload form. Instead, I’m going to make the case for TypeScript on behalf of a company that doesn’t want or need my evangelism. Here’s my reasoning:
If the user interactions are simple enough, you can probably write the front-end without a framework. I’d still want to keep my front-end source pretty modular and the output minified. I’d use something like esbuild for that.
you haven’t said enough about what your goals are to answer this question in a way that can really go beyond being a popularity contest for various languages. Most language can parse text, interact with a database, and serve a JSON API these days, so those requirements aren’t really a lot to run with. What should it run on? How many users? How does the data get there? What does the save state look like? Is parsing the save state data a difficult parsing problem? Do you have to reverse the format or do you already know it? Should other people be able to run the server? Will you want people to log in? Are you trying to learn a skill that you can get paid to use? Are you trying to expand your brain?
Anyway use Go I guess.
I don’t have a favorite language/framework/library for this kind of project. It’s more about how easy it’ll be to host it somewhere that won’t cost me anything or very little. In this case, it seems like it won’t be a massive amount of visitors (older video game) and a database could be anything but let’s say SQLite. With these requirements, if you go with Go, you still need to find somewhere to run your binary. With Python, you’ll find some cheap hosting like OVH, same with PHP. Always keep it as simple as possible to get your base project working and then improve on it once you’ve learned more. You could even use glitch.com and use a file based DB.
I’m not an evangelist for any language, but I’d suggest Go, Elixir or Clojure.
Why not play a game? Pick some outward-facing feature you’ve always wanted to code in a CRUD app. Perhaps you’ve always wanted to make a SPA, or use the .NET ASP stuff under linux. Maybe there’s a CASE engine for a database (or a database feature) that’s supposed to expose tables for simple CRUD.
There are a lot of different things you can show or play with in the end result. Pick something you’ve either wanted to do or would really like to know how it works. Once you’ve picked the end-result, choose the code/language/platform/framework that you think would be the best match for that thing. This way you’ve got a better question than simply “What’s cool?” and when you’re done you can evaluate your experience with what the boosters said.