ProgrammingPro #88: Go Shared Memory Fixes, 100 Common Python Errors, 10 AI-Powered Dev Tools, and a Malicious Go Package
Welcome to a brand new issue of ProgrammingPro.
In today’s Expert Insight, we bring you an excerpt from the recently published book, Go Recipes for Developers, which demonstrates how to manage shared memory in Go by avoiding memory races and using mutexes to synchronize access to shared variables, instead of relying solely on channels.
News Highlights: 10 AI tools gain new features, including Amazon Q’s code validation; a malicious Go package evades detection for years; Stack Exchange tests AI answers despite a past ban; and Java updates JDK, frameworks, and tooling.
My top 5 picks from today’s learning resources:
But there’s more, so dive right in.
Stay Awesome!
Divya Anne Selvaraj
Editor-in-Chief
🗞️News and Analysis🔎
10 development tools that have recently added new AI capabilities: Covers Amazon Q’s real-time code validation, DeepSeek R1’s availability on Azure AI, JetBrains' Junie coding agent, Sourcegraph’s AI code reviewers, and more.
Java News Roundup: Java Operator SDK 5.0, Open Liberty, Quarkus MCP, Vert.x, JBang, TornadoVM: Also covers updates to JDK 24 and 25, Spring Cloud, Infinispan, and JHipster Lite.
Malicious package found in the Go ecosystem: The typosquat package mimicking BoltDB contains a backdoor for remote code execution and exploited the Go Module Mirror’s indefinite caching, evading detection for over three years!
Rust update fixes ‘forever’ compilation: Rust 1.84.1 fixes regressions from Rust 1.84, including a severe slowdown caused by the next-gen trait solver, errors in overlapping impls, duplicate-crate diagnostics, and missing debug info.
TypeScript checks returns for conditional and indexed access types: TypeScript 5.8, now in beta, introduces limited type checking for conditional and indexed access types in return statements, reducing reliance on type assertions.
Apple open sources Swift Build: The engine used by Xcode, to unify build systems across Xcode and Swift Package Manager (Swift PM), is now available on GitHub under the Apache 2.0 license and supports multiple platforms.
Stack Exchange dabbles with AI answers – despite Stack Overflow banning them in 2022: The experiment, limited to select sites, requires human verification before AI answers become public and aims to boost engagement.
🎓Tutorials and Learning Resources💡
Python
💡100 Common Python Mistakes: Covers logic bugs, inefficient code, non-Pythonic practices, and best practices for readability and performance, using clear examples for each mistake.
For more Python resources, go to PythonPro
C# and .NET
💡Top 10 .NET Performance Anti-Patterns You Should Fix Today: Covers excessive object allocation, blocking async calls, inefficient database queries, and overusing reflection, and provides fixes such as using object pooling.
🎓Tutorial | Build Intelligent Apps with .NET and DeepSeek R1: Using the Microsoft.Extensions.AI (MEAI) library, it provides a step-by-step guide for connecting to GitHub Models, Azure AI Foundry, or running locally with Ollama.
🎓Tutorial | Writing a .NET Garbage Collector in C# - Part 2: Covers defining key interfaces (IGCHeap, IGCHandleManager, IGCHandleStore), handling GC handles, implementing memory allocation, and more.
C and C++
💡21st Century C++: In this article, Bjarne Stroustrup recommends modern C++ practices for performance, type safety, and maintainability, covering resource management, modularity, generic programming, and more.
💡Starflate: Deflate decompression in C++23: Discusses lessons learned from the development of Starflate, a Deflate decompression implementation in C++23, covering the Deflate algorithm, project design, and more.
💡I Wrote a Wasm Interpreter in C: Covers the author's experience writing Semblance, a WebAssembly interpreter in C, detailing the WebAssembly specification, interpreter design, and implementation of function calls and host imports.
Java
🎓Tutorial | How to Compile Java into Native Binaries with Mill and Graal: Explains the setup, build process, benefits like faster startup and lower memory usage, and limitations such as longer build times and restricted reflection support.
💡The Java Streams Parallel: Provides an in-depth analysis of Java Streams' parallel execution, including its implementation, concurrency behavior, stream operation characteristics, and internal design in JDK 24.
💡Java's synchronized explained: Explains how Java’s
synchronized
keyword works at the bytecode level, detailingmonitorenter
andmonitorexit
instructions, object monitors, and how synchronized methods differ from synchronized blocks.
JavaScript and TypeScript
💡Is npm Enough? Why Startups are Coming after this JavaScript Package Registry: Examines emerging competition in the JavaScript package management space, focusing on how Deno’s JSR and vlt’s vsr challenge npm’s dominance.
🤯Someone got Linux running inside a PDF file, because its users are something else: The project exploits the PDF format’s JavaScript support to enable computation, with user input via a virtual keyboard and text box translating to on-screen actions.
🎓Tutorial | Slots: Make your Angular API flexible: Explores how content projection in Angular can make UI components more flexible and reusable, comparing ng-content and ng-template.
Go
🎓Tutorial | How Databases Work Under the Hood: Building a Key-Value Store in Go: Explains how databases store and retrieve data efficiently by managing query layers and storage engines.
🎓Tutorial | Dealing with Golang Data Types: Explains Golang’s data types' memory considerations, practical applications, and syntax, with examples, and concludes with coding exercises.
Rust
💡No-Panic Rust: A Nice Technique for Systems Programming: Discusses how, by carefully designing APIs and leveraging Rust’s optimizer, developers can write efficient, panic-free Rust code.
🎓Tutorial | Making System Calls in Rust: Requesting Services from the Kernel: Explains how to use the
libc
crate to access low-level kernel services, with examples on file I/O, handling processes viafork()
, and more.
Swift
💡Rethinking Our Color System: A Type-Safe Approach in Swift: Discusses rethinking a color system in Swift using type safety, generics, and property wrappers instead of subclassing
UIColor
.🎓Tutorial | Parameterized tests in Swift: Reducing boilerplate code: Explains how to improve test clarity, and make debugging easier by running a single test with multiple input values.
PHP
💡The State of PHP 2024: Reveals that PHP remains a dominant force in web development, with Laravel as the leading framework, PhpStorm as the preferred IDE, increasing AI adoption, and ongoing efforts to enhance PHP’s features.
SQL
🎓Tutorial | Query Tuning in DBSQL with the new V2 Query Profile: Introduces a streamlined tool for query tuning in DBSQL, helping users quickly identify bottlenecks through execution summaries, detailed scan insights, and the new "Top Operators" feature.
Ruby
🎓Tutorial | Setting Up a Rails 8 with Vite and Tailwind CSS 4: Covers installation, configuration, and integration of Turbo, Stimulus, and Tailwind with Vite for modern frontend development in Rails.
🎓Tutorial | Ruby on Rails on WebAssembly, the full-stack in-browser journey: Details the process of "wasmifying" a Rails app, adapting database storage, leveraging service workers, and the future potential of Rails.
Kotlin
🎓Tutorial | Kotlin Constants in Android: Top-level vs. Companion-enclosed: Analyzes their effect on APK size, memory usage, and performance through bytecode inspection and R8 optimizations.
💡10+ Common Kotlin Coroutine Mistakes Senior Android Developers Should Avoid: Covers blocking the main thread, improper exception handling, misusing coroutine scopes, overusing withContext, and more.
🌟Advanced Concepts🚀
Do Code LLMs Understand Design Patterns?: Examines whether Code LLMs understand design patterns by evaluating their ability to recognize, comprehend, and generate pattern-compliant code.
Comprehensive Guide to AI Workflow Design Patterns with PydanticAI code examples: Covers prompt chaining, routing, parallelization, orchestrator-workers, evaluator-optimizer workflows, and autonomous agents.
Building a Serverless Fan-Out-Fan-In Mechanism: Explains how to implement a serverless fan-out-fan-in mechanism using AWS Step Functions, SNS, SQS, and DynamoDB to build scalable and fault-tolerant distributed systems.
How has DeepSeek improved the Transformer architecture?: Explains how DeepSeek v3 enhances the Transformer architecture through multi-head latent attention (MLA), mixture-of-experts (MoE) improvements, and multi-token prediction.
🧠Expert Insight📚
Here’s an excerpt from “Chapter 7: Concurrency" in the book, Go Recipes for Developers, by Burak Serdar, published in December 2024.
Sharing memory
One of the most famous Go idioms is: “Do not communicate by sharing memory, share memory by communicating.” Channels are for sharing memory by communicating. Communicating by sharing memory is done using shared variables in multiple goroutines. Even though it is
discouraged, there are many use cases where shared memory makes more sense than a channel. If at least one of the goroutines updates a shared variable that is read by other goroutines, you have to ensure that there are no memory races.
A memory race happens when a goroutine updates a variable concurrently while another goroutine reads from it or writes to it. When this happens, there is no guarantee that the update to that variable will be seen by other goroutines. A famous example of this situation is the busy-wait
loop:
func main() {
done:=false
go func() {
// Wait while done==false
for !done {}
fmt.Println("Done is true now")
}()
done=true
// Wait indefinitely
select{}
}
This program has a memory race. The done=true
assignment is concurrent with the for !done
loop. That means, even though the main goroutine runs done=true
, the goroutine reading done
may never see that update, staying in the for
loop indefinitely.
Updating shared variables concurrently
The Go memory model guarantees that the effect of a variable write is visible to instructions that come after that write within that goroutine only. That is, if you update a shared variable, you have to use special tools to make that update visible to other goroutines. A simple way to ensure this is to use a mutex. Mutex stands for “mutual exclusion.” A mutex is a tool you can use to ensure the following:
Only one goroutine updates a variable at any given time
Once that update is done and the mutex is released, all goroutines can see that update
In this recipe, we show how this is done.
How to do it...
The section of a program that updates shared variables is a “critical section.” You use a mutex to ensure that only a single goroutine can enter its critical section.
Declare a mutex to protect a critical section:
// cacheMutex will be used to protect access to cache
var cacheMutex sync.Mutex
var cache map[string]any = map[string]any{}
A mutex protects a set of shared variables. For instance, if you have goroutines that update a single integer, you declare a mutex for the critical sections that update that integer. You must use the same mutex every time you read or write that integer value.
When updating the shared variable(s), first lock the mutex. Then perform the update and unlock the mutex:
cacheMutex.Lock()
cache[key]=value
cacheMutex.Unlock()
With this pattern, if multiple goroutines attempt to update cache
, they will queue at cacheMutex.Lock()
and only one will be allowed. When that goroutine performs the update, it will call cacheMutex.Unlock()
, which will enable one of the waiting goroutines to acquire the lock and update the cache again.
When reading the shared variable, first lock the mutex. Then perform the read, and then unlock the mutex:
cacheMutex.Lock()
cachedValue, cached := cache[key]
cacheMutex.Unlock()
if cached {
// Value found in cache
}
Go Recipes for Developers was published in December 2024. Packt library subscribers can continue reading the entire book for free or you can buy the book here!
Get the eBook for $31.99 $21.99
🛠️Useful Tools⚒️
lume: A lightweight CLI and local API server for managing macOS and Linux virtual machines with near-native performance on Apple Silicon, using Apple's Virtualization.Framework.
klarity: Analyzes uncertainty in generative model outputs using probability entropy and semantic understanding to reveal model behavior and hallucination risks.
iterm-mcp: A Model Context Protocol (MCP) server that enables models to inspect, interact with, and control an active iTerm session efficiently.
That’s all for today.
We have an entire range of newsletters with focused content for tech pros. Subscribe to the ones you find the most useful here.
If your company is interested in reaching an audience of developers, software engineers, and tech decision makers, you may want to advertise with us.
If you have any suggestions or feedback, or would like us to find you a learning resource on a particular subject, just leave a comment below!